前端时间我们开发了基于Net的一套搭建sprint.NET+NHibernate+MVC+WCF+EasyUI等中小型企业级系统开发平台,现在把整个开发过程中的步步进展整理出来和大家分享,这个系列可能有点长,多多指导学习。
我们的底层开发平台是sprint.NET+NHibernate+MVC+WCF+EasyUI方式开发,顺便加点Spring.net注入的部分,当然我们最主要的关于权限设计、业务设计,而架构,咱们没有学过太复杂的架构,我们还是以最常用的MVC架构开始拓展
参考材料:
<<重构,改善既有代码的设计>>
<<.net应用架构设计原则,模式与实践>>
<<.net设计范式>>
<<代码整洁之道>>
首先我们要讲解一下关于项目的搭建部分,我们的项目主要分6部分,业务逻辑层,数据访问层,页面层,数据模型层以及一个公共类的部分,每层我们在这个基础上抽象了对应的接口,这样上一层只需要对下一层,面向接口编程,同时有Spring.NET来管理层之间的关系,达到解耦的目的。
这里主要是:
业务逻辑层:
ICMSBLL:业务逻辑层接口
CMSBLL:业务逻辑层实现
抽象的数据底层封装(泛型)
ICommonSupportDAL:对公共的方法的抽象
CommonSupportDAL:公共方法的实现
数据访问层:
ICMSDAL:数据访问层接口
CMSDAL:数据访问层实现
领域模型层:
Entity:这是EF建立的模型
集合类层:
Collections:封装了分页,对于集合类内部的增删改查,对集合类内部类的增删改查。
界面层:
ComplaintManageSystem:主要的MVC和LigerUI实现的界面部分
TZHSWEET.UI:关于MVC公共UI定义的部分
公共类库部分:
我们的目标是“0”增删改查的数据访问层实现,主要是靠Nhibernate的定义通用的增删改从,然后其他类继承增删改查接口和相应的自定义的子类的接口,实现拓展
首先,我们从以前的写代码经验知道,我们的Dao主要是做增删改查等方面,我们就先定义一个公共方法的接口叫做ICommonSupportDAL,这个接口定义泛型增删改查
<span style="font-family:FangSong_GB2312;font-size:18px;">using System; using System.Collections.Generic; using System.Linq; using System.Text; using Entity; namespace ICommonSupportDAL { public interface IRepository<T, TCollection> where T : class { #region 即时查询,通过ID查询 /// <summary> /// 获取实体 /// </summary> /// <param name="id">主键</param> /// <returns>实体</returns> T Get(object id); #endregion #region 延迟加载,通过ID查询 /// <summary> /// 获取实体 /// </summary> /// <param name="id">主键</param> /// <returns>实体</returns> T Load(T entity); #endregion #region 将数据持久化到数据库 /// <summary> /// 插入实体 /// </summary> /// <param name="entity">实体</param> /// <returns>ID</returns> object Save(T entity); #endregion #region 更新数据信息 /// <summary> /// 修改实体 /// </summary> /// <param name="entity">实体</param> void Update(T entity); #endregion #region 若数据存在则修改信息,若不存在则插入 /// <summary> /// 若数据存在则修改信息,若不存在则插入 /// </summary> /// <param name="entity">实体</param> void SaveOrUpdate(T entity); #endregion #region 删除实体 /// <summary> /// 删除实体 /// </summary> /// <param name="id">ID</param> void Delete(T entity); #endregion #region 根据ID批量删除实体 //删除实体 //void Delete(T entity); /// <summary> /// 根据ID批量删除实体 /// </summary> /// <param name="idList">ID集合</param> void Delete(IList<T> idList); #endregion /// <summary> /// 获取全部集合 /// </summary> /// <returns>集合</returns> //IQueryable<T> LoadAll(); /// <summary> /// 分页获取全部集合 /// </summary> /// <param name="count">记录总数</param> /// <param name="pageIndex">页码</param> /// <param name="pageSize">每页大小</param> /// <returns>集合</returns> //IQueryable<T> LoadAllWithPage(out long count, int pageIndex, int pageSize); #region 无条件查询所有实体(单表查询) /// <summary> /// 无条件查询所有实体(单表查询) /// </summary> /// <param name="sql"></param> /// <returns></returns> TCollection LoadAll(); #endregion #region 通过自己写where条件查询实体 /// <summary> /// 通过自己写where条件查询实体 /// </summary> /// <param name="whereSql"></param> /// <returns></returns> TCollection LoadAllByWhereSql(object whereSql); #endregion #region 根据某一条件字段删除 /// <summary> /// 按条件删除 /// </summary> /// <param name="columName">字段名</param> /// <param name="columValue">字段值</param> void DeleteAfterQuery(object columName, object columValue); #endregion #region 按一个条件查询(单表查询) /// <summary> /// 按一个条件查询 /// </summary> /// <param name="columnName"></param> /// <param name="columValue"></param> /// <returns></returns> TCollection getByCondition(object columnName, object columValue); #endregion #region 通过原生sql语句进行增删改查操作 /// <summary> /// 通过原生sql语句进行增删改查操作 /// </summary> /// <param name="sql"></param> /// <returns></returns> TCollection ExecuteOrQueryBySql(object sql); #endregion #region 多条件查询 /// <summary> /// 多条件查询 /// </summary> /// <returns></returns> TCollection FindVer(QueryHelper<T> qh); #endregion #region 根据SQL语句查询 /// <summary> /// 根据SQL语句查询 /// </summary> /// <param name="sql"></param> /// <returns></returns> TCollection LoadAllBySql(string sql); #endregion #region 根据某一字段查询(多表查询) /// <summary> /// 根据某一字段查询(多表查询) /// </summary> /// <param name="columnName"></param> /// <param name="columValue"></param> /// <returns></returns> TCollection LoadByCondition(object columnName, object columValue); #endregion } } </span>
这层接口,大家可能认为没什么必要,但是,这个接口非常重要,这个接口保证了我们用Nhibernate一个抽象类实现增删改查的同时又增加了子类的自身扩展性.
接下来,就是Dao部分,我们需要很慎重的去设计,
首先我们要设计一个用Nhibernate实现的公共父类的CommonSupportDAL类,用它来实现增删改查,
<span style="font-family:FangSong_GB2312;font-size:18px;"><span style="color:#000000;">using System; using System.Collections.Generic; using System.Linq; using System.Text; using Spring.Data.NHibernate.Generic.Support; using NHibernate; using System.Linq.Expressions; using System.Collections; using ICommonSupportDAL; using Entity; using MCS.Library.Data.DataObjects; using System.Reflection; using Collections; namespace CommonSupportDAL { /// <summary> /// 数据访问层公共接口实现 /// </summary> /// <typeparam name="T">实体泛型</typeparam> public class RepositoryBase<T, TCollection> : HibernateDaoSupport, IRepository<T, TCollection> where T : class where TCollection : Collection<T, TCollection> ,new() { public String TEntityName; public RepositoryBase() { String name = typeof(T).ToString(); this.TEntityName = name.Substring(name.LastIndexOf('.') + 1); } #region 将实体持久化到数据库 /// <summary> /// 将实体持久化到数据库 /// </summary> /// <param name="entity">泛型实体</param> /// <returns></returns> public virtual object Save(T entity) { // this.HibernateTemplate.Find<T>("from UserInfo "); try { this.HibernateTemplate.SessionFactory.GetCurrentSession().FlushMode = FlushMode.Auto; }catch(Exception ex) { } Object TEntity = this.HibernateTemplate.Save(entity); this.HibernateTemplate.Flush(); return TEntity; } #endregion #region 根据ID查询 /// <summary> /// 根据ID查询 /// </summary> /// <param name="id"></param> /// <returns></returns> public virtual T Get(object id) { return this.HibernateTemplate.Get<T>(id); } #endregion #region 根据ID查询 /// <summary> /// 根据ID查询 /// </summary> /// <param name="id">实体ID</param> /// <returns></returns> public virtual T Load(T entity) { Object fild=null; try { fild = entity.GetType().GetProperty("ID").GetValue(entity, null); } catch (Exception ex) { string typename = entity.GetType().ToString(); throw new Exception("请检查" + typename + "中是否存在主键ID!"); } return this.HibernateTemplate.Load<T>(fild); } #endregion #region 查询所有实体信息 /// <summary> /// 查询所有实体信息 /// </summary> /// <returns></returns> public virtual TCollection LoadAll() { TCollection tcollecton = new TCollection(); IList<T> list = this.HibernateTemplate.LoadAll<T>(); tcollecton.CopyFrom(list); return tcollecton; } #endregion #region 根据条件查询实体集合信息(hql) /// <summary> /// 根据条件查询实体集合信息(hql) /// </summary> /// <returns></returns> public virtual TCollection LoadAllByWhereSql(object whereSql) { TCollection tcollecton = new TCollection(); IList<T> list = this.HibernateTemplate.Find<T>("from " + TEntityName + " where " + whereSql); tcollecton.CopyFrom(list); return tcollecton; } #endregion #region 根据条件查询实体集合信息(sql) /// <summary> /// 根据条件查询实体集合信息(sql) /// </summary> /// <returns></returns> public virtual TCollection LoadAllBySql(string sql) { TCollection tcollecton = new TCollection(); IList<T> list = this.HibernateTemplate.Find<T>(sql); tcollecton.CopyFrom(list); return tcollecton; } #endregion #region 更新实体信息 /// <summary> /// 更新实体信息 /// </summary> /// <param name="entity"></param> public virtual void Update(T entity) { this.HibernateTemplate.SessionFactory.GetCurrentSession().FlushMode = FlushMode.Auto; this.HibernateTemplate.Update(entity); this.HibernateTemplate.Flush(); } #endregion #region 根据ID删除信息 /// <summary> /// 根据ID删除信息 /// </summary> /// <param name="id"></param> public void Delete(T entity) { this.HibernateTemplate.SessionFactory.GetCurrentSession().FlushMode = FlushMode.Auto; this.HibernateTemplate.Delete(entity); this.HibernateTemplate.Flush(); } #endregion #region 批量删除 /// <summary> /// 批量删除 /// </summary> /// <param name="idList"></param> public virtual void Delete(IList<T> idList) { foreach (object item in idList) { this.HibernateTemplate.SessionFactory.GetCurrentSession().FlushMode = FlushMode.Auto; this.HibernateTemplate.Delete(item); this.HibernateTemplate.Flush(); } } #endregion #region 按条件删除 /// <summary> ///按条件删除 /// </summary> /// <param name="columName"></param> /// <param name="columValue"></param> public virtual void DeleteAfterQuery(object columName, object columValue) { IList<T> list = this.HibernateTemplate.Find<T>("from " + TEntityName + " u where u." + columName + " =?", new object[] { columValue }); //在执行删除 foreach (object t in list) { this.HibernateTemplate.SessionFactory.GetCurrentSession().FlushMode = FlushMode.Auto; this.HibernateTemplate.Delete(t); this.HibernateTemplate.Flush(); } } #endregion #region 保存后更新 /// <summary> /// 保存后更新 /// </summary> /// <param name="entity"></param> public virtual void SaveOrUpdate(T entity) { this.HibernateTemplate.SessionFactory.GetCurrentSession().FlushMode = FlushMode.Auto; this.HibernateTemplate.SaveOrUpdate(entity); this.HibernateTemplate.Flush(); } #endregion //#region ///// <summary> ///// 根据条件查询实体集合信息--sql语句,不推荐使用,会产生sql注入 ///// </summary> ///// <returns></returns> //public virtual IList<T> getBywhereSql(string wheresql) //{ // IList<T> list = this.HibernateTemplate.Find<T>("from " + TName + " where " + wheresql); // return list; //} //#endregion //#region //#endregion ///// <summary> ///// 根据条件查询实体集合信息--sql语句,不推荐使用,会产生sql注入 ///// </summary> ///// <returns></returns> //public virtual IList<T> getBySql(string sql) //{ // IList<T> list = this.HibernateTemplate.Find<T>(sql); // return list; //} #region 通过一个条件查询(单表查询) /// <summary> /// 通过一个条件查询(单表查询) /// </summary> /// <param name="columName">属性名</param> /// <param name="columValue">属性值</param> /// <returns></returns> public virtual TCollection getByCondition(object columnName, object columValue) { TCollection tcoll = new TCollection(); //比如验证用户名,只需要传入Name属性的名称和值即可; //这个Name是对应的实体的属性名称,非数据库字段名。例getByCondition("Name","11"); IList<T> list = this.HibernateTemplate.Find<T>("from " + TEntityName + " u where u." + columnName + " =?", new object[] { columValue }); tcoll.CopyFrom(list); return tcoll; } #endregion #region 通过一个条件查询(多表查询) /// <summary> /// 通过一个条件查询(单表查询) /// </summary> /// <param name="columName">属性名</param> /// <param name="columValue">属性值</param> /// <returns></returns> public virtual TCollection LoadByCondition(object columnName, object columValue) { TCollection tcoll = new TCollection(); //比如验证用户名,只需要传入Name属性的名称和值即可; //这个Name是对应的实体的属性名称,非数据库字段名。例getByCondition("Name","11"); IList<T> list = this.HibernateTemplate.Find<T>("from " + TEntityName + " u where u." + columnName + " =?", new object[] { columValue }); tcoll=this.LoadById(list); return tcoll; } #endregion #region 通过原生sql语句进行增删改查操作 /// <summary> /// 通过原生sql语句进行增删改查操作 /// </summary> /// <param name="sql"></param> /// <returns></returns> public TCollection ExecuteOrQueryBySql(object sql) { TCollection tcollecton = new TCollection(); ISQLQuery sqlQuery = this.HibernateTemplate.SessionFactory.GetCurrentSession().CreateSQLQuery(sql.ToString()).AddEntity(typeof(T)); tcollecton.CopyFrom(sqlQuery.List<T>()); return tcollecton; } #endregion #region 多条件查询 /// <summary> /// 多条件查询 /// </summary> /// <returns></returns> public TCollection FindVer(QueryHelper<T> qh) { // QueryHelper<T> qh = new QueryHelper<T>("u"); //return qh; // 参数列表 IList<Object> parameters = qh.getParameters(); // 查询本页的数据列表 IQuery listQuery = this.HibernateTemplate.SessionFactory.GetCurrentSession().CreateQuery(qh.getListQueryHql()); // 创建查询对象 if (parameters != null) { // 设置参数 for (int i = 0; i < parameters.Count; i++) { listQuery.SetParameter(i, parameters[i]); } } listQuery.List(); TCollection tcollection = new TCollection(); IList<T> list = listQuery.List<T>(); tcollection.CopyFrom(list); return tcollection; } #endregion #region 分页查询 /// <summary> /// 分页查询 /// </summary> /// <param name="tcollection"></param> /// <returns></returns> public TCollection LoadAllByPage(TCollection tcollection) { IQuery query = this.HibernateTemplate.SessionFactory.OpenSession().CreateQuery("from "+typeof(T).ToString()); query.SetFirstResult((tcollection.PageNum - 1) * tcollection.PageSize); query.SetMaxResults(tcollection.PageSize); IList list = query.List(); TCollection tcoll = new TCollection(); tcoll.TotalRecords=this.LoadAll().Count(); IEnumerator en = list.GetEnumerator(); while (en.MoveNext()) { tcoll.Add((T)en.Current); } //tcoll.CopyFrom(list); return tcoll; } #endregion #region 通过多个ID查询 /// <summary> /// 通过多个ID查询 /// </summary> /// <param name="entity">包含ID信息的实体集合</param> /// <returns>集合信息</returns> public TCollection LoadById(IList<T> entity) { IEnumerator en = entity.GetEnumerator(); IList<object> IDlist = new List<object>(); while (en.MoveNext()) { Object fild = null; try { fild = en.Current.GetType().GetProperty("ID").GetValue(en.Current, null); } catch (Exception ex) { string typename = en.Current.GetType().ToString(); throw new Exception("请检查" + typename + "中是否存在主键ID!"); } IDlist.Add("'"+fild+"'"); } IQuery query = this.HibernateTemplate.SessionFactory.OpenSession().CreateQuery("from " + TEntityName + " u where u.ID in (" +string.Join(",",IDlist.ToArray())+")"); // IQuery query = this.HibernateTemplate.SessionFactory.OpenSession().CreateQuery("from " + TEntityName + " u where u.ID in ('05221ff5-b491-4590-86bb-f5e275c6fd83','10df07ac-98ae-41f8-bcde-c4f48ec931f4','14c33f83-3be7-4162-8ace-8ef2e3677402','29780cc4-d7d8-4982-b8b7-ee63320da1d8','299ad880-06e3-48a3-80ca-570b8a557c42','7662b072-42a7-45fc-b11b-93efc844e5cd','87c26a14-56f2-4a57-9c99-e55f55ba6cdd','87c73291-591b-431f-b0fe-e73e15a490cf','917f9354-29e2-44b0-ad58-e2d8a0dd7670','9de57d2d-b4f8-4c56-9ce6-66673f42413d','a0e0cb9a-e8e4-4164-a021-cbcb61a8ea30','c6c239bf-6089-4c7c-983c-8ca479c360d5','c996d768-c9f9-4575-9268-4cfcf92fd038','ca09c55e-0a8d-4241-a364-74f1bdb60c32','da34ebae-11a7-4cfc-9772-b5e049768fe7','e5ee288e-8c5d-46bc-8c77-34b8c45750c1')"); IList list= query.List(); TCollection tc= new TCollection(); IEnumerator enumer=list.GetEnumerator(); while(enumer.MoveNext()) { tc.Add((T)enumer.Current); } return tc; } #endregion } }</span> </span>
<span style="font-family:FangSong_GB2312;font-size:18px;"><span style="color:#000000;"> public interface ICaseAssignEntityRepository:IRepository<CaseAssignEntity,CaseAssignEntityCollection> { }</span></span>
<span style="font-family:FangSong_GB2312;font-size:18px;">namespace CMSDAL.AnJianLuRu { public class CaseAssignEntityRepository : RepositoryBase<CaseAssignEntity, CaseAssignEntityCollection>, ICaseAssignEntityRepository { } }</span>
大家看到继承了两个一个是RepositoryBase父类,一个是ICaseAssignEntityRepository自己的业务逻辑接口(实现了子类的拓展,比如在某个类中想要添加这个类特有的方法,只需要在自己的接口中填写即可),通过这个继承体系保证了我们在实现增删改查的同时外放一个接口保证扩展性.
继承系列图:
总结
这样我们的数据访问层,很轻松的实现了,基本上代码量非常少,增删改查部分几乎"0"代码,都是泛型的父类实现了.抽象、继承、泛型、委托、容器等等大大提高了代码的复用性。-----一切来源于抽象!
今天就讲解到这里,接下来给大家讲解Collection的封装与抽象,期待!