前几节的内容比较务虚,这一节主要讲讲怎么应用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
看起来,似乎是繁琐到发指的一些工作,不过形成习惯了应该就会喜欢上它的,眼下的麻烦只是为了避免未来更大的麻烦,图难图其易图巨图其细嘛~