前几节的内容比较务虚,这一节主要讲讲怎么应用Spring.net和nHibernate及我们写的模板,来搭建一个数据访问层,以及在页面中的调用。
先来看一个层级图:
这里有一个model(实体)层,一个DAO(数据访问)层,中间还有一个Interface(接口)层。 这又回到了最初的探索:接口的做用,一是隐藏实现的细节;二是更利于装配——在spring.net的配置文件中,你可以随时装配一个不同的实现,只要它完成接口规定的方法,好处不言而喻——于页面而言,它并不知道谁来实现了这些功能,它只知道接口的存在(你们都去实现接口吧,我不关心谁在做这件事,要的只是结果!)
◆欧克,现在页面需要一个对用户表访问的东西(TB_USER_MAIN表,对应的实体是woodigg.model.USERMAIN),先做一个接口,在woodigg.Interface层添加一个接口:
Code
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层中引用此项目,然后添加一个实现:
Code
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的对象工厂实例化并派发它:
Code
<? 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:
Code
<? 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中:
Code
< 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接口的实现,就能让它跑起来了:
Code
#region 注入对象 private IUserMainDAO _UserMainDaoSpring; public IUserMainDAO UserMainDaoSpring { get { return _UserMainDaoSpring; } set { _UserMainDaoSpring = value; } } #endregion
看起来,似乎是繁琐到发指的一些工作,不过形成习惯了应该就会喜欢上它的,眼下的麻烦只是为了避免未来更大的麻烦,图难图其易图巨图其细嘛~ 下一节,我们来看看web services怎么注入。