首先附上本人托管在Github上的项目https://github.com/lichaojacobs/Tomato
线上地址:www.wanhb.cn
接下来的三层结构都包含了父接口,子接口,父类,子类部分
1、编写数据访问层
数据访问层是对数据库的增删改查的操作。首先我们在数据访问层的父接口声明一些通用的对数据库统一处理的方法:
1 #region 1.0 新增 实体 +int Add(T model) 2 /// <summary> 3 /// 新增 实体 4 /// </summary> 5 /// <param name="model"></param> 6 /// <returns></returns> 7 int Add(T model); 8 #endregion 9 10 #region 2.0 根据 id 删除 +int Del(T model) 11 /// <summary> 12 /// 根据 id 删除 13 /// </summary> 14 /// <param name="model">包含要删除id的对象</param> 15 /// <returns></returns> 16 int Del(T model); 17 #endregion 18 19 #region 3.0 根据条件删除 +int DelBy(Expression<Func<T, bool>> delWhere) 20 /// <summary> 21 /// 3.0 根据条件删除 22 /// </summary> 23 /// <param name="delWhere"></param> 24 /// <returns></returns> 25 int DelBy(Expression<Func<T, bool>> delWhere); 26 #endregion 27 28 #region 4.0 修改 +int Modify(T model, params string[] proNames) 29 /// <summary> 30 /// 4.0 修改,如: 31 /// T u = new T() { uId = 1, uLoginName = "asdfasdf" }; 32 /// this.Modify(u, "uLoginName"); 33 /// </summary> 34 /// <param name="model">要修改的实体对象</param> 35 /// <param name="proNames">要修改的 属性 名称</param> 36 /// <returns></returns> 37 int Modify(T model, params string[] proNames); 38 #endregion 39 40 #region 4.0 批量修改 +int Modify(T model, Expression<Func<T, bool>> whereLambda, params string[] modifiedProNames) 41 /// <summary> 42 /// 4.0 批量修改 43 /// </summary> 44 /// <param name="model">要修改的实体对象</param> 45 /// <param name="whereLambda">查询条件</param> 46 /// <param name="proNames">要修改的 属性 名称</param> 47 /// <returns></returns> 48 int ModifyBy(T model, Expression<Func<T, bool>> whereLambda, params string[] modifiedProNames); 49 #endregion 50 51 #region 5.0 根据条件查询 +List<T> GetListBy(Expression<Func<T,bool>> whereLambda) 52 /// <summary> 53 /// 5.0 根据条件查询 +List<T> GetListBy(Expression<Func<T,bool>> whereLambda) 54 /// </summary> 55 /// <param name="whereLambda"></param> 56 /// <returns></returns> 57 List<T> GetListBy(Expression<Func<T, bool>> whereLambda); 58 #endregion 59 60 #region 5.1 根据条件 排序 和查询 + List<T> GetListBy<TKey> 61 /// <summary> 62 /// 5.1 根据条件 排序 和查询 63 /// </summary> 64 /// <typeparam name="TKey">排序字段类型</typeparam> 65 /// <param name="whereLambda">查询条件 lambda表达式</param> 66 /// <param name="orderLambda">排序条件 lambda表达式</param> 67 /// <returns></returns> 68 List<T> GetListBy<TKey>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderLambda); 69 #endregion 70 71 #region 6.0 分页查询 + List<T> GetPagedList<TKey> 72 /// <summary> 73 /// 6.0 分页查询 + List<T> GetPagedList<TKey> 74 /// </summary> 75 /// <param name="pageIndex">页码</param> 76 /// <param name="pageSize">页容量</param> 77 /// <param name="whereLambda">条件 lambda表达式</param> 78 /// <param name="orderBy">排序 lambda表达式</param> 79 /// <returns></returns> 80 List<T> GetPagedList<TKey>(int pageIndex, int pageSize, Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderBy); 81 #endregion
然后是数据访问层子接口(对应于你的数据实体模型中的Model,下面是我的项目中的Model,仅供参考),让它继承自业务层父接口
1 2 3 using System; 4 using System.Collections.Generic; 5 using System.Linq; 6 using System.Text; 7 8 namespace IDAL 9 { 10 public partial interface IsysdiagramsDAL : IBaseDAL<Model.sysdiagrams> 11 { 12 13 14 } 15 16 public partial interface IT001账号表DAL : IBaseDAL<Model.T001账号表> 17 { 18 19 20 } 21 22 public partial interface IT002验证表DAL : IBaseDAL<Model.T002验证表> 23 { 24 25 26 } 27 28 public partial interface IT003用户角色表DAL : IBaseDAL<Model.T003用户角色表> 29 { 30 31 32 } 33 34 public partial interface IT004社团信息表DAL : IBaseDAL<Model.T004社团信息表> 35 { 36 37 38 } 39 40 public partial interface IT005票务表DAL : IBaseDAL<Model.T005票务表> 41 { 42 43 44 } 45 46 public partial interface IT006店铺信息表DAL : IBaseDAL<Model.T006店铺信息表> 47 { 48 49 50 } 51 52 public partial interface IT007店铺货物表DAL : IBaseDAL<Model.T007店铺货物表> 53 { 54 55 56 } 57 58 public partial interface IT008海报信息表DAL : IBaseDAL<Model.T008海报信息表> 59 { 60 61 62 } 63 64 public partial interface IT009社团账号表DAL : IBaseDAL<Model.T009社团账号表> 65 { 66 67 68 } 69 70 71 }
写完接口,接下来编写父接口的实现父类BaseDAL.cs,在实现类中获得一个数据上下文类用来操作数据库
1 using System; 2 using System.Collections.Generic; 3 using System.Data.Entity.Infrastructure; 4 using System.Linq; 5 using System.Linq.Expressions; 6 using System.Reflection; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Data.Entity; 10 11 namespace DAL 12 { 13 public class BaseDAL<T>:IDAL.IBaseDAL<T> where T:class,new() 14 { 15 //1,定义上下文对象 16 // Model.TomatoEntities db = new Model.TomatoEntities(); 17 protected DbContext db = new DBContextFactory().GetDbContext(); 18 19 //2,定义增删改查的操作 20 #region 1.0 新增 实体 +int Add(T model) 21 /// <summary> 22 /// 新增 实体 23 /// </summary> 24 /// <param name="model"></param> 25 /// <returns></returns> 26 public int Add(T model) 27 { 28 db.Set<T>().Add(model); 29 return db.SaveChanges();//保存成功后,会将自增的id设置给 model的 主键属性,并返回受影响行数 30 } 31 #endregion 32 33 #region 2.0 根据 id 删除 +int Del(T model) 34 /// <summary> 35 /// 根据 id 删除 36 /// </summary> 37 /// <param name="model">包含要删除id的对象</param> 38 /// <returns></returns> 39 public int Del(T model) 40 { 41 db.Set<T>().Attach(model); 42 db.Set<T>().Remove(model); 43 return db.SaveChanges(); 44 } 45 #endregion 46 47 #region 3.0 根据条件删除 +int DelBy(Expression<Func<T, bool>> delWhere) 48 /// <summary> 49 /// 3.0 根据条件删除 50 /// </summary> 51 /// <param name="delWhere"></param> 52 /// <returns></returns> 53 public int DelBy(Expression<Func<T, bool>> delWhere) 54 { 55 //3.1查询要删除的数据 56 List<T> listDeleting = db.Set<T>().Where(delWhere).ToList(); 57 //3.2将要删除的数据 用删除方法添加到 EF 容器中 58 listDeleting.ForEach(u => 59 { 60 db.Set<T>().Attach(u);//先附加到 EF容器 61 db.Set<T>().Remove(u);//标识为 删除 状态 62 }); 63 //3.3一次性 生成sql语句到数据库执行删除 64 return db.SaveChanges(); 65 } 66 #endregion 67 68 #region 4.0 修改 +int Modify(T model, params string[] proNames) 69 /// <summary> 70 /// 4.0 修改,如: 71 /// T u = new T() { uId = 1, uLoginName = "asdfasdf" }; 72 /// this.Modify(u, "uLoginName"); 73 /// </summary> 74 /// <param name="model">要修改的实体对象</param> 75 /// <param name="proNames">要修改的 属性 名称</param> 76 /// <returns></returns> 77 public int Modify(T model,params string[] proNames) 78 { 79 //int idreal = (int)id; 80 //var ent = db.Set<T>().Find(idreal); 81 //if (ent != null) 82 //{ 83 // db.Entry<T>(model).State = System.Data.EntityState.Detached; 84 //} 85 //4.1将 对象 添加到 EF中 86 DbEntityEntry entry = db.Entry<T>(model); 87 88 ///跟踪对象 89 db.Set<T>().Attach(model); 90 //4.2先设置 对象的包装 状态为 Unchanged 91 entry.State = System.Data.EntityState.Unchanged; 92 //4.3循环 被修改的属性名 数组 93 foreach (string proName in proNames) 94 { 95 //4.4将每个 被修改的属性的状态 设置为已修改状态;后面生成update语句时,就只为已修改的属性 更新 96 entry.Property(proName).IsModified = true; 97 } 98 //4.4一次性 生成sql语句到数据库执行 99 return db.SaveChanges(); 100 } 101 #endregion 102 103 #region 4.0 批量修改 +int Modify(T model, Expression<Func<T, bool>> whereLambda, params string[] modifiedProNames) 104 /// <summary> 105 /// 4.0 批量修改 106 /// </summary> 107 /// <param name="model">要修改的实体对象</param> 108 /// <param name="whereLambda">查询条件</param> 109 /// <param name="proNames">要修改的 属性 名称</param> 110 /// <returns></returns> 111 public int ModifyBy(T model, Expression<Func<T, bool>> whereLambda, params string[] modifiedProNames) 112 { 113 //4.1查询要修改的数据 114 List<T> listModifing = db.Set<T>().Where(whereLambda).ToList(); 115 116 //获取 实体类 类型对象 117 Type t = typeof(T); // model.GetType(); 118 //获取 实体类 所有的 公有属性 119 List<PropertyInfo> proInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList(); 120 //创建 实体属性 字典集合 121 Dictionary<string, PropertyInfo> dictPros = new Dictionary<string, PropertyInfo>(); 122 //将 实体属性 中要修改的属性名 添加到 字典集合中 键:属性名 值:属性对象 123 proInfos.ForEach(p => 124 { 125 if (modifiedProNames.Contains(p.Name)) 126 { 127 dictPros.Add(p.Name, p); 128 } 129 }); 130 131 //4.3循环 要修改的属性名 132 foreach (string proName in modifiedProNames) 133 { 134 //判断 要修改的属性名是否在 实体类的属性集合中存在 135 if (dictPros.ContainsKey(proName)) 136 { 137 //如果存在,则取出要修改的 属性对象 138 PropertyInfo proInfo = dictPros[proName]; 139 //取出 要修改的值 140 object newValue = proInfo.GetValue(model, null); //object newValue = model.uName; 141 142 //4.4批量设置 要修改 对象的 属性 143 foreach (T usrO in listModifing) 144 { 145 //为 要修改的对象 的 要修改的属性 设置新的值 146 proInfo.SetValue(usrO, newValue, null); //usrO.uName = newValue; 147 } 148 } 149 } 150 //4.4一次性 生成sql语句到数据库执行 151 return db.SaveChanges(); 152 } 153 #endregion 154 155 #region 5.0 根据条件查询 +List<T> GetListBy(Expression<Func<T,bool>> whereLambda) 156 /// <summary> 157 /// 5.0 根据条件查询 +List<T> GetListBy(Expression<Func<T,bool>> whereLambda) 158 /// </summary> 159 /// <param name="whereLambda"></param> 160 /// <returns></returns> 161 public List<T> GetListBy(Expression<Func<T, bool>> whereLambda) 162 { 163 return db.Set<T>().Where(whereLambda).ToList(); 164 } 165 #endregion 166 167 #region 5.1 根据条件 排序 和查询 + List<T> GetListBy<TKey> 168 /// <summary> 169 /// 5.1 根据条件 排序 和查询 170 /// </summary> 171 /// <typeparam name="TKey">排序字段类型</typeparam> 172 /// <param name="whereLambda">查询条件 lambda表达式</param> 173 /// <param name="orderLambda">排序条件 lambda表达式</param> 174 /// <returns></returns> 175 public List<T> GetListBy<TKey>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderLambda) 176 { 177 return db.Set<T>().Where(whereLambda).OrderBy(orderLambda).ToList(); 178 } 179 #endregion 180 181 #region 6.0 分页查询 + List<T> GetPagedList<TKey> 182 /// <summary> 183 /// 6.0 分页查询 + List<T> GetPagedList<TKey> 184 /// </summary> 185 /// <param name="pageIndex">页码</param> 186 /// <param name="pageSize">页容量</param> 187 /// <param name="whereLambda">条件 lambda表达式</param> 188 /// <param name="orderBy">排序 lambda表达式</param> 189 /// <returns></returns> 190 public List<T> GetPagedList<TKey>(int pageIndex, int pageSize, Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderBy) 191 { 192 // 分页 一定注意: Skip 之前一定要 OrderBy 193 return db.Set<T>().Where(whereLambda).OrderBy(orderBy).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); 194 } 195 #endregion 196 197 } 198 }
注意,在这里是通过一个工具类(DBContextFactory)获得了数据实体的上下文对象,通过这个工具类可以在一个线程中共享上下文对象,从而节省系统资源开销也可以缓解数据库的压力
1 using System; 2 using System.Collections.Generic; 3 using System.Data.Entity; 4 using System.Linq; 5 using System.Runtime.Remoting.Messaging; 6 using System.Text; 7 8 namespace DAL 9 { 10 public class DBContextFactory:IDAL.IDBContextFactory 11 { 12 #region 创建 EF上下文 对象,在线程中共享 一个 上下文对象 + DbContext GetDbContext() 13 /// <summary> 14 /// 创建 EF上下文 对象,在线程中共享 一个 上下文对象 15 /// </summary> 16 /// <returns></returns> 17 public DbContext GetDbContext() 18 { 19 //从当前线程中 获取 EF上下文对象 20 DbContext dbContext = CallContext.GetData(typeof(DBContextFactory).Name) as DbContext; 21 if (dbContext == null) 22 { 23 dbContext = new Model.TomatoEntities(); 24 //将新创建的 ef上下文对象 存入线程 25 CallContext.SetData(typeof(DBContextFactory).Name, dbContext); 26 } 27 return dbContext; 28 } 29 #endregion 30 } 31 }
2、搭建业务逻辑层
这个过程与数据访问层类似(业务层调用数据访问层相关方法),不多说了,直接上代码
业务父接口(方法的声明与数据访问层父接口相同):
直接参考上文的数据访问层的父接口的方法声明
业务子接口(继承业务父接口,实现扩展):
1 2 3 using System; 4 using System.Collections.Generic; 5 using System.Linq; 6 using System.Text; 7 8 namespace IBLL 9 { 10 public partial interface IsysdiagramsBLL : IBaseBLL<Model.sysdiagrams> 11 { 12 13 } 14 15 public partial interface IT001账号表BLL : IBaseBLL<Model.T001账号表> 16 { 17 18 } 19 20 public partial interface IT002验证表BLL : IBaseBLL<Model.T002验证表> 21 { 22 23 } 24 25 public partial interface IT003用户角色表BLL : IBaseBLL<Model.T003用户角色表> 26 { 27 28 } 29 30 public partial interface IT004社团信息表BLL : IBaseBLL<Model.T004社团信息表> 31 { 32 33 } 34 35 public partial interface IT005票务表BLL : IBaseBLL<Model.T005票务表> 36 { 37 38 } 39 40 public partial interface IT006店铺信息表BLL : IBaseBLL<Model.T006店铺信息表> 41 { 42 43 } 44 45 public partial interface IT007店铺货物表BLL : IBaseBLL<Model.T007店铺货物表> 46 { 47 48 } 49 50 public partial interface IT008海报信息表BLL : IBaseBLL<Model.T008海报信息表> 51 { 52 53 } 54 55 public partial interface IT009社团账号表BLL : IBaseBLL<Model.T009社团账号表> 56 { 57 58 } 59 60 61 }
实现父类以及子类:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Linq.Expressions; 5 using System.Text; 6 using System.Threading.Tasks; 7 8 9 namespace BLL 10 { 11 public abstract class BaseBLL<T> : IBLL.IBaseBLL<T> where T : class,new() 12 { 13 public BaseBLL() 14 { 15 SetDAL(); 16 } 17 18 19 20 //1,定义数据操作层父接口类 21 protected DAL.BaseDAL<T> idal= new DAL.BaseDAL<T>(); 22 /// <summary> 23 /// 由子类实现,为 业务父类 里的 数据接口对象 设置 值! 24 /// </summary> 25 public abstract void SetDAL(); 26 27 28 //2,定义增删改查的方法 29 //2.增删改查方法 30 #region 1.0 新增 实体 +int Add(T model) 31 /// <summary> 32 /// 新增 实体 33 /// </summary> 34 /// <param name="model"></param> 35 /// <returns></returns> 36 public int Add(T model) 37 { 38 return idal.Add(model); 39 } 40 #endregion 41 42 #region 2。0 根据 用户 id 删除 +int Del(int uId) 43 /// <summary> 44 /// 根据 用户 id 删除 45 /// </summary> 46 /// <param name="uId"></param> 47 /// <returns></returns> 48 public int Del(T model) 49 { 50 return idal.Del(model); 51 } 52 #endregion 53 54 #region 3.0 根据条件删除 +int DelBy(Expression<Func<T, bool>> delWhere) 55 /// <summary> 56 /// 3.0 根据条件删除 57 /// </summary> 58 /// <param name="delWhere"></param> 59 /// <returns></returns> 60 public int DelBy(Expression<Func<T, bool>> delWhere) 61 { 62 return idal.DelBy(delWhere); 63 } 64 #endregion 65 66 #region 4.0 修改 +int Modify(T model, params string[] proNames) 67 /// <summary> 68 /// 4.0 修改,如: 69 /// </summary> 70 /// <param name="model">要修改的实体对象</param> 71 /// <param name="proNames">要修改的 属性 名称</param> 72 /// <returns></returns> 73 public int Modify(T model, params string[] proNames) 74 { 75 return idal.Modify(model, proNames); 76 } 77 #endregion 78 79 #region 4.0 批量修改 +int Modify(T model, Expression<Func<T, bool>> whereLambda, params string[] modifiedProNames) 80 /// <summary> 81 /// 4.0 批量修改 +int Modify(T model, Expression<Func<T, bool>> whereLambda, params string[] modifiedProNames) 82 /// </summary> 83 /// <param name="model"></param> 84 /// <param name="whereLambda"></param> 85 /// <param name="modifiedProNames"></param> 86 /// <returns></returns> 87 public int ModifyBy(T model, Expression<Func<T, bool>> whereLambda, params string[] modifiedProNames) 88 { 89 return idal.ModifyBy(model, whereLambda, modifiedProNames); 90 } 91 #endregion 92 93 #region 5.0 根据条件查询 +List<T> GetListBy(Expression<Func<T,bool>> whereLambda) 94 /// <summary> 95 /// 5.0 根据条件查询 +List<T> GetListBy(Expression<Func<T,bool>> whereLambda) 96 /// </summary> 97 /// <param name="whereLambda"></param> 98 /// <returns></returns> 99 public List<T> GetListBy(Expression<Func<T, bool>> whereLambda) 100 { 101 return idal.GetListBy(whereLambda); 102 } 103 #endregion 104 105 #region 5.1 根据条件 排序 和查询 + List<T> GetListBy<TKey> 106 /// <summary> 107 /// 5.1 根据条件 排序 和查询 108 /// </summary> 109 /// <typeparam name="TKey">排序字段类型</typeparam> 110 /// <param name="whereLambda">查询条件 lambda表达式</param> 111 /// <param name="orderLambda">排序条件 lambda表达式</param> 112 /// <returns></returns> 113 public List<T> GetListBy<TKey>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderLambda) 114 { 115 return idal.GetListBy(whereLambda, orderLambda); 116 } 117 #endregion 118 119 #region 6.0 分页查询 + List<T> GetPagedList<TKey> 120 /// <summary> 121 /// 6.0 分页查询 + List<T> GetPagedList<TKey> 122 /// </summary> 123 /// <param name="pageIndex">页码</param> 124 /// <param name="pageSize">页容量</param> 125 /// <param name="whereLambda">条件 lambda表达式</param> 126 /// <param name="orderBy">排序 lambda表达式</param> 127 /// <returns></returns> 128 public List<T> GetPagedList<TKey>(int pageIndex, int pageSize, Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderBy) 129 { 130 return idal.GetPagedList(pageIndex, pageSize, whereLambda, orderBy); 131 } 132 #endregion 133 134 } 135 }
子类的实现
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Linq.Expressions; using IBLL; using IDAL; namespace BLL { public partial class sysdiagramsBLL: BaseBLL<Model.sysdiagrams>,IsysdiagramsBLL { public override void SetDAL() { } } public partial class T001账号表BLL: BaseBLL<Model.T001账号表>,IT001账号表BLL { public override void SetDAL() { idal = DAL.BaseDAL<T001账号表DAL>(); } } public partial class T002验证表BLL: BaseBLL<Model.T002验证表>,IT002验证表BLL { public override void SetDAL() { idal = DAL.BaseDAL<T002验证表DAL>(); } } public partial class T003用户角色表BLL: BaseBLL<Model.T003用户角色表>,IT003用户角色表BLL { public override void SetDAL() { idal =DAL.BaseDAL<T003用户角色表DAL>(); } } public partial class T004社团信息表BLL: BaseBLL<Model.T004社团信息表>,IT004社团信息表BLL { public override void SetDAL() { idal = DAL.BaseDAL<T004社团信息表DAL>();; } } public partial class T005票务表BLL: BaseBLL<Model.T005票务表>,IT005票务表BLL { public override void SetDAL() { idal = DAL.BaseDAL<T005票务表DAL>(); } } public partial class T006店铺信息表BLL: BaseBLL<Model.T006店铺信息表>,IT006店铺信息表BLL { public override void SetDAL() { idal = DAL.BaseDAL<T006店铺信息表DAL>(); } } public partial class T007店铺货物表BLL: BaseBLL<Model.T007店铺货物表>,IT007店铺货物表BLL { public override void SetDAL() { idal =DAL.BaseDAL<T007店铺货物表DAL>(); } } public partial class T008海报信息表BLL: BaseBLL<Model.T008海报信息表>,IT008海报信息表BLL { public override void SetDAL() { idal =DAL.BaseDAL<T008海报信息表DAL>(); } } public partial class T009社团账号表BLL: BaseBLL<Model.T009社团账号表>,IT009社团账号表BLL { public override void SetDAL() { idal = DAL.BaseDAL<T009社团账号表DAL>(); } } }
3、表现层的简单调用:
IBLL.IT001账号表BLL user=new BLL.T001账号表BLL();
user.GetListBy(m => m.Email =="");//lambda表达式
注:限于篇幅和时间,现在离spring.net 以及工厂化模式还很遥远,以后我会继续更新,有兴趣可以看一下github上的项目,已经实现控制反转与工厂模式