前几节的内容比较务虚,这一节主要讲讲怎么应用Spring.net和nHibernate及我们写的模板,来搭建一个数据访问层,以及在页面中的调用。
先来看一个层级图:
这里有一个model(实体)层,一个DAO(数据访问)层,中间还有一个Interface(接口)层。
这又回到了最初的探索:接口的做用,一是隐藏实现的细节;二是更利于装配——在spring.net的配置文件中,你可以随时装配一个不同的实现,只要它完成接口规定的方法,好处不言而喻——于页面而言,它并不知道谁来实现了这些功能,它只知道接口的存在(你们都去实现接口吧,我不关心谁在做这件事,要的只是结果!)
◆欧克,现在页面需要一个对用户表访问的东西(TB_USER_MAIN表,对应的实体是woodigg.model.USERMAIN),先做一个接口,在woodigg.Interface层添加一个接口:
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using woodigg.model;
namespace woodigg.Interface.DAO
{
/// <summary>
/// user main DAO Interface
/// </summary>
public interface IUserMainDAO
{
/// <summary>
/// 存
/// </summary>
bool Save(USERMAIN mb);
/// <summary>
/// 事务级添加
/// </summary>
/// <param name="art"></param>
/// <param name="from"></param>
/// <returns></returns>
bool TransactionSave(USERMAIN art, string from);
/// <summary>
/// 更新
/// </summary>
bool Update(USERMAIN mb);
/// <summary>
/// 事务级删除
/// </summary>
bool Delete(USERMAIN mb);
/// <summary>
/// 读
/// </summary>
USERMAIN LoadFromId(int id);
/// <summary>
/// 搜索
/// </summary>
IList<USERMAIN> SearchByWhere(string where);
/// <summary>
/// 搜索排序
/// </summary>
IList<USERMAIN> SearchByWhereOrder(string where, string propertyName, bool ascending);
/// <summary>
/// 分页
/// </summary>
DataTable GetPagerByStoreProc(string Columns, int pageSize, int pageIdx
, string OrderColumn, bool orderType, string condition);
/// <summary>
/// 获取记录数
/// </summary>
int GetRecordCount(string where);
}
}
◆显然,它的功能都是上一节那个DaoTemplate泛型模板已经有的,要实现真的很easy——编译刚才的woodigg.Interface项目,并在woodigg.DAO层中引用此项目,然后添加一个实现:
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using Spring.Context;
using Spring.Context.Support;
using Spring.Dao;
using Spring.Data.NHibernate.Support;
using woodigg.model;
using woodigg.Interface.DAO;
using Spring.Transaction.Interceptor;
namespace woodigg.DAO
{
/// <summary>
/// user main DAO
/// </summary>
public class UserMainDaoSpring : IUserMainDAO
{
#region 注入的DaoTemplate
private DaoTemplate _DaoTemplate;
public DaoTemplate DaoTemplate
{
get { return _DaoTemplate; }
set { _DaoTemplate = value; }
}
#endregion
private const string TableName = "TB_USER_MAIN"; //表名
private const string PrimaryKey = "Id"; //主键
public UserMainDaoSpring() { }
/// <summary>
/// 存
/// </summary>
public bool Save(USERMAIN art)
{
return DaoTemplate.Save<USERMAIN>(art);
}
/// <summary>
/// 事务级添加
/// </summary>
/// <param name="art"></param>
/// <param name="from">从哪来</param>
/// <returns></returns>
[Transaction()]
public bool TransactionSave(USERMAIN art, string from)
{
if (DaoTemplate.Save<USERMAIN>(art))
{
USEROTHER ot = new USEROTHER();
ot.UserId = art.Id;
ot.UserFrom = from;
return DaoTemplate.Save<USEROTHER>(ot);
}
else
return false;
}
/// <summary>
/// 更新
/// </summary>
/// <param name="art"></param>
/// <returns></returns>
public bool Update(USERMAIN art)
{
return DaoTemplate.Update<USERMAIN>(art);
}
/// <summary>
/// 删除
/// </summary>
/// <param name="art"></param>
[Transaction()]
public bool Delete(USERMAIN art)
{
DaoTemplate.Delete<USEROTHER>("UserId=" + art.Id);
return DaoTemplate.Delete<USERMAIN>(art);
}
/// <summary>
/// 读
/// </summary>
public USERMAIN LoadFromId(int id)
{
return DaoTemplate.LoadFromId<USERMAIN>(id);
}
/// <summary>
/// 查
/// </summary>
public IList<USERMAIN> SearchByWhere(string where)
{
return DaoTemplate.Search<USERMAIN>(where);
}
/// <summary>
/// 查排序
/// </summary>
public IList<USERMAIN> SearchByWhereOrder(string where,string propertyName,bool ascending)
{
return DaoTemplate.SearchWithOrder<USERMAIN>(where,propertyName,ascending);
}
/// <summary>
/// 分页
/// </summary>
/// <param name="pageSize"></param>
/// <param name="pageIdx"></param>
/// <param name="OrderColumn"></param>
/// <param name="orderType"></param>
/// <param name="condition"></param>
/// <returns></returns>
public DataTable GetPagerByStoreProc(string Columns,int pageSize, int pageIdx
, string OrderColumn, bool orderType, string condition)
{
return DaoTemplate.GetPageEntitesByStoredProc
(TableName, PrimaryKey, Columns, OrderColumn, pageSize, pageIdx, orderType, condition);
}
/// <summary>
/// 获取记录数
/// </summary>
/// <param name="where"></param>
public int GetRecordCount(string where) {
return DaoTemplate.GetRecordCount<USERMAIN>(where);
}
}
}
◆为这种类型的DAL制作一个配置文件business.xml,以便在需要时,由spring.net的对象工厂实例化并派发它:
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd"
>
<object id="UserMainDaoSpring" type="woodigg.DAO.UserMainDaoSpring,woodigg.DAO" autowire="byName" />
</objects>
◆至此,一个所谓的DAL打造完成,把它应用到.aspx页面中去(当然,实例中比这复杂得多,以后我们会在ASP.NET MVC中应用这些,页面只是个壳)。为了.aspx页面,做一个配置文件pageConfig.xml吧,在这个xml里,登记所有需要注入的页面路径,以便植入实现了接口的DAL:
假设这页面在/下,叫test.aspx:
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd"
>
<!--页面调用-->
<object type="~/test.aspx" autowire="byName" />
</objects>
如前所述,byName的意思是:页面上写什么接口,就自动去配置环境中查找相应接口实现,并把它在工厂中的实例注入页面中。
◆然后,我们整合一下应用环境,把它配置到web.config中:
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.WebContextHandler, Spring.Web"/>
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>
</sectionGroup>
<section name="SpringOverrideProperty" type="System.Configuration.NameValueSectionHandler"/>
<section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<!--log4net-->
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
</configSections>
<SpringOverrideProperty>
<add key="DbProvider.ConnectionString" value="Data Source=(local);Database=Music;User ID=sa;Password=system;Trusted_Connection=False"/>
<add key="SystemInit.IsDebug" value="true"/>
<add key="SystemInit.Level" value="4"/>
</SpringOverrideProperty>
<!-- Spirng.Net 配置 -->
<spring>
<context>
<resource uri="config://spring/objects"/>
<resource uri="~/config/applicationContext.xml"/>
<resource uri="~/config/business.xml"/>
<resource uri="~/config/pageConfig.xml"/>
</context>
<objects xmlns="http://www.springframework.net"/>
</spring>
<system.web>
<httpModules>
<add name="Spring" type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
</httpModules>
<httpHandlers>
<add verb="*" path="*.aspx" type="Spring.Web.Support.PageHandlerFactory, Spring.Web"/>
</system.web>
</httpHandlers>
</system.web>
◆最后,test.aspx.cs中,这样引用前面基于IUserMainDAO接口的实现,就能让它跑起来了:
#region 注入对象
private IUserMainDAO _UserMainDaoSpring;
public IUserMainDAO UserMainDaoSpring
{
get { return _UserMainDaoSpring; }
set { _UserMainDaoSpring = value; }
}
#endregion
看起来,似乎是繁琐到发指的一些工作,不过形成习惯了应该就会喜欢上它的,眼下的麻烦只是为了避免未来更大的麻烦,图难图其易图巨图其细嘛~
下一节,我们来看看web services怎么注入。