打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
『Spring.NET NHibernate 泛型』框架搭建之DAO(三)★

  本节内容介绍Nhibernate所封装的数据库访问层。不过我加入了泛型进行封装。大概思路:首先,我们有一个接口层,还有一个对应的实现层;在接口层中我们先定义一个父接口,父接口中定义每一个接口都可能会用到的方法,然后其他接口继承此父接口即可。如果子接口需要使用特殊的方法,可以单独定义在子接口中;在接口实现层中也是类似的,定义一个父类,里面写好实现了接口层父接口的方法,其他实现层同样继承父接口和实现层父类,接口层中定义的特殊方法也在对应的实现类中进行实现。这样做可以有效的把相似的重复代码(重复的增删改查)尽可能的减少,并且这样设计比较灵活,重复的写一次就行了,特殊的单独写,维护起来也比较方便。这样描述可能不是很明白,下面详细介绍实现步骤。


一、数据库访问接口层IDAO

  1. 在解决方案上右键新建一个类库,命名为IDAO,用来存放Nhibernae数据库访问接口层代码,并添加引用上一节所讲的实体层Model

  2. 在类库中添加一个父接口,命名为IDAO,并定义常用的方法,代码如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace IDAO{ public interface IDAO { /// /// 添加实体 /// /// int Add(T entity); /// /// 修改实体 /// /// void Update(T entity); /// /// 保存或修改实体 /// /// void SaveOrUpdate(IList list); /// /// 删除实体 /// /// void Delete(T entity); /// /// 按条件删除 /// /// 删除条件 void Delete(string sqlWhere); /// /// 根据ID得到实体 /// /// /// T Get(int id); /// /// 根据ID得到实体 /// /// /// T Load(int id); /// /// 得到所有实体 /// /// IList LoadAll(); /// /// 按条件排序得到前N条记录 /// /// 获取条数 /// 排序字段 /// 排序方式,升序asc,降序desc /// IList QueryTop(int top, string field, string order); /// /// 根据条件得到实体 /// /// 查询条件 /// IList Where(string sqlWhere); /// /// 得到统计数量 /// /// 查询条件 /// int GetRecordCount(string strWhere); /// /// 分页获取数据列表 /// /// 每页获取数据条数 /// 当前页是第几页 /// 查询条件 /// IList GetPageList(int PageSize, int PageIndex, string strWhere); /// /// 根据数据字典父编码和编码获取名称 /// /// 父编码 /// 编码 /// string GetName(string parentNumber, string number); /// /// 获取该父编码下最大编码 /// /// 父编码 /// int GetMaxNumber(string parentNumber); }}

  3.定义好了父接口,下面定义子接口,还是以IT_RoleDAO为例,代码如下:

using System;using Model;namespace IDAO{ public interface IT_RoleDAO : IDAO { }}


  这样,IT_RoleDAO就拥有了IDAO定义了的方法,如果IT_RoleDAO有特殊方法,直接添加在IT_RoleDAO里面即可,以IT_AreaDAO为例,代码如下:

using System;using Model;namespace IDAO{ public interface IT_AreaDAO : IDAO { /// /// 获取 /// /// /// int GenerateAreaNumber(string parentNumber); }}


  最后,我们看一下IDAO层的文件目录:


二、NHibernate数据库访问实现层NHibernateDAO(核心)

  1. 在解决方案上右键新建一个类库,命名为NHibernateDAO,用来存放Nhibernae数据库访问实现层代码,并添加引用上一节所讲的实体层Model和接口层IDAO

  2. 右键点击引用,选择“管理NuGet程序包”,选择“联机”,搜索“Spring.NET”,在搜索结果中选择“Spring.Net NHibernate 4 support”安装。该安装包括了一个NHibernate,但是还不够,同样的方法搜索NHibernate,并安装,添加Nhibernate就不上图了,添加Spring.NET的界面图如下:




  3.添加数据库访问层父类NHibernateDAO,NHibernateDAO类中的SessionFactory属性的GetCurrentSession方法可以实例化ISession,实例化ISession后的对象可以调用NHibernate下的数据库操作方法,具体他们之间怎么实例化,先上代码,后面再来解释。


  NHibernateDAO代码如下,继承INHibernateSessionFactory和实现IDAO父接口:

using System;using System.Collections;using System.Collections.Generic;using System.Linq;using Model;using IDAO;using NHibernate;using NHibernate.Criterion;using NHibernate.Linq;using Spring.Data.NHibernate.Support;using NHibernate.Cfg;using System.Text;namespace NHibernateDAO{ [Spring.Stereotype.Repository] public class NHibernateDAO : IDAO { public ISessionFactory SessionFactory { get; set; } /// /// 获取Session /// public ISession Session { get { return SessionFactory.GetCurrentSession(); } } /// /// 当前实体对应的表名 /// public string TableName { get { return typeof(T).ToString().Substring(typeof(T).ToString().LastIndexOf('.') + 1); } } /// /// 添加实体 /// /// public int Add(T entity) { using (ITransaction transaction = Session.BeginTransaction()) { try { int id = (int)Session.Save(entity); Session.Flush(); transaction.Commit(); return id; } catch (HibernateException) { transaction.Rollback(); throw; } } } /// /// 修改实体 /// /// public void Update(T entity) { using (ITransaction transaction = Session.BeginTransaction()) { try { Session.Update(entity); Session.Flush(); transaction.Commit(); } catch (HibernateException) { transaction.Rollback(); throw; } } } /// /// 保存或修改实体 /// /// public void SaveOrUpdate(IList list) { using (ITransaction transaction = Session.BeginTransaction()) { try { foreach (var entity in list) { Session.SaveOrUpdate(entity); } Session.Flush(); transaction.Commit(); } catch (HibernateException) { transaction.Rollback(); throw; } } } /// /// 删除实体 /// /// public void Delete(T entity) { using (ITransaction transaction = Session.BeginTransaction()) { try { Session.Delete(entity); Session.Flush(); transaction.Commit(); } catch (HibernateException) { transaction.Rollback(); throw; } } } /// /// 按条件删除 /// /// 删除条件 public void Delete(string sqlWhere) { using (ITransaction transaction = Session.BeginTransaction()) { try { Session.Delete(string.Format('from {0} Where {1}', TableName, sqlWhere)); Session.Flush(); transaction.Commit(); } catch (HibernateException) { transaction.Rollback(); throw; } } } /// /// 根据ID得到实体 /// /// /// public T Get(int id) { return Session.Get(id); } /// /// 根据ID得到实体 /// /// /// public T Load(int id) { return Session.Load(id); } /// /// 得到所有实体 /// /// public IList LoadAll() { return Session.Query().ToList(); } /// /// 按条件排序得到前N条记录 /// /// 获取条数 /// 排序字段 /// 排序方式,升序asc,降序desc /// public IList QueryTop(int top, string field, string order) { if (order == 'asc') { return Session.CreateCriteria(typeof(T)).SetMaxResults(top).AddOrder(Order.Asc(field)).List(); } else { return Session.CreateCriteria(typeof(T)).SetMaxResults(top).AddOrder(Order.Desc(field)).List(); } } /// /// 根据条件得到实体 /// /// 查询条件 /// public IList Where(string sqlWhere) { StringBuilder strSql = new StringBuilder(string.Format('from {0} c', TableName)); if (!string.IsNullOrEmpty(sqlWhere)) { strSql.Append(string.Format(' where {0}', sqlWhere)); } return Session.CreateQuery(strSql.ToString()).List(); } /// /// 得到统计数量 /// /// 查询条件 /// public int GetRecordCount(string sqlWhere) { StringBuilder strSql = new StringBuilder(string.Format('select count(1) from {0} c', TableName)); if (!string.IsNullOrEmpty(sqlWhere)) { strSql.Append(string.Format(' where {0}', sqlWhere)); } return (int)Session.CreateSQLQuery(strSql.ToString()).UniqueResult(); } /// /// 分页获取数据列表 /// /// 每页获取数据条数 /// 当前页是第几页 /// 查询条件 /// public IList GetPageList(int PageSize, int PageIndex, string sqlWhere) { StringBuilder strSql = new StringBuilder(); strSql.Append(string.Format('select top {0} * from {1} where ID not in(select top ', PageSize, TableName)); strSql.Append(PageSize * (PageIndex - 1)); strSql.Append(string.Format(' ID from {0}', TableName)); if (!string.IsNullOrEmpty(sqlWhere)) { strSql.Append(string.Format(' where {0} ) and {0}', sqlWhere)); } else { strSql.Append(')'); } return Session.CreateSQLQuery(strSql.ToString()).AddEntity(typeof(T)).List(); } /// /// 根据数据字典父编码和编码获取名称 /// /// 父编码 /// 编码 /// public string GetName(string parentNumber, string number) { string[] num = number.Split(','); List list = new List(); list.AddRange(num); IQueryable name = from q in Session.Query() where q.ParentNumber == parentNumber && list.Contains(q.Number) orderby q.Number select q.Name; string nameStr = ''; foreach (string n in name) { nameStr += n + ','; } return nameStr.Contains(',') ? nameStr.Substring(0, nameStr.Length - 1) : nameStr; } /// /// 获取该父编码下最大编码 /// /// 父编码 /// public int GetMaxNumber(string parentNumber) { string strSql = string.Format( 'select case when MAX(cast(substring(Number,len(Number)-3,4) as int)) is null then 0 else MAX(cast(substring(Number,len(Number)-3,4) as int)) end from {0} where ParentNumber='{1}'', TableName, parentNumber); return ++Session.CreateQuery(strSql).List()[0]; } }}


  4. 添加一个数据库访问层实现类,以T_RoleDAO为例:

using System;using System.Collections;using IDAO;using Model;namespace NHibernateDAO{ public class T_RoleDAO : NHibernateDAO, IT_RoleDAO { }}


  同样滴,继承NHibernateDAO并实现IT_RoleDAO接口,他便拥有了他们定义好的方法。如果有特殊方法代码如下:

using System;using System.Collections;using Model;using IDAO;using System.Text;using System.Collections.Generic;using NHibernate;namespace NHibernateDAO{ public class T_AreaDAO : NHibernateDAO,IT_AreaDAO { public int GenerateAreaNumber(string parentNumber) { string sqlStr = string.Format(@'select case when MAX(cast(Number as int)) is null then 0 else MAX(cast(Number as int)) end from {0} where ParentNumber={1}', TableName, parentNumber); return ++Session.CreateQuery(sqlStr).List()[0]; } }}

  5. 下面,就来解释一下他们都是怎么实例化的。这里就用到Spring.NET依赖注入的方式实现,先看配置文件。在NHibernateDAO类库下添加文件夹Config,用来存放配置文件,然后添加一个命名为objects.xml的xml。这里必须定义每一个数据库访问层对象,不能说他们都继承NHibernateDAO,只定义NHibernateDAO,这样的话会报错,因为后面BLL层要调用DAO层,他们之间是一一对应的,这里先简单提一下,后面讲到就明白了。代码如下:



  格式如上述代码,先定义一个objects根节点,然后再objects中定义每一个数据库访层,type指定“命名空间.类名,命名空间”,property指定属性,name必须与NHibernateDAO中的SessionFactory相同,由于每一个数据库访问层都继承了NHibernateDAO,所有他们就拥有了NHibernateDAO的属性SessionFactory,ref指定SessionFactory实例化的对象,NHibernateSessionFactory是NHibernate框架封装的数据库访问类。所以,我们看到我们没有在代码中实实例化SessionFactory,只是定义了一个属性,而是通过Spring.NET的配置文件来把SessionFactory实例化的,这就是所谓的依赖注入,也交控制反转。


  6. 细心的撸友可以发现了,数据库操作的类和方法我们定义好了,但是数据访问的连接字符串还没有,下面就来配置数据库访问文件。同样在NHibernateDAO的Config中添加DataAccess.xml,代码如下:

数据访问的配置信息 包括:DbProvider NHibernate Model

  其中connectionString='Data Source=${db.server};Database=${db.database};User ID=${db.userid} ;PassWord=${db.password}中,我并没有明确指定他们访问地址、数据库等。这是一种类似定义一个变量的方式指定他们的访问地址、数据库等信息的,具体变量的值是什么,会在后面web层的config配置文件中定义,按这个格式写就行,先不用纠结。这样也方便维护。


  最后,还是看一下NHibernateDAO层的目录结构:





本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
hibernate HQL 模糊查询 3种方式
NHibernate入门级示例(增 删 改)
简单实现Hibernate分表的select,insert,delete及所有操作
NHibernate快速指南(翻译
博客园 - Terrylee的技术专栏 - 基于NHibernate的三层结构应用程序开发初步
NHibernate Quick Start Guide
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服