快速开发框架第二弹:让ORM为快速开发插上翅膀(2)改进和基础框架搭建
在上一篇的文章中,那样的封装让开发变的很爽,好吧,我承认这是面向数据库编程的思维。在一个类中,封装了单表的几乎所有操作,我的看法是,因为ORM封装了所有的与数据库打交道的操作,它就是项目中的数据交换层,由于这个泛型类封装了单对象的操作,那么使得我们独立了所有对象的基本操作,使复用达到最高,使我们关注点集中了在对象关系处理和复杂的业务逻辑中。(希望有经验的人能给我指导或者相互讨论)
一.让封装回归正途 多数据库的支持
public class BaseDao<T> where T : Entity { public DbSession db; public BaseDao(DbSession _db) { db = _db; } public BaseDao(): this(DbSession.Default) { } #region "查询" /// <summary> /// 通过条件得到对象 /// </summary> /// <param name="where"></param> /// <returns>如果你的条件是得到单个 那么list《T》[0]就是这个对象</returns> public virtual List<T> Get_Entity_byWhere(WhereClip where, OrderByClip orderby, params Field[] fields) { return db.From<T>() .Where(where) .Select(fields) .OrderBy(orderby) .ToList(); } /// <summary> /// 得到DataTable数据集合 /// </summary> /// <param name="where"></param> /// <param name="orderby"></param> /// <param name="fields"></param> /// <returns></returns> public virtual DataTable Get_Entity_byWhere_ToTable(WhereClip where, OrderByClip orderby, params Field[] fields) { return db.From<T>() .Where(where) .Select(fields) .OrderBy(orderby) .ToTable(); } /// <summary> /// 通过条件得到单个对象 /// </summary> /// <param name="where"></param> /// <param name="fields"></param> /// <returns></returns> public virtual T Get_SingleEntity_byWhere(WhereClip where, params Field[] fields) { return db.From<T>() .Where(where) .Select(fields) .ToSingle(); } /// <summary> /// 得到所有的数据 /// </summary> /// <returns>datatable</returns> public virtual DataTable Get_AllData_Table() { return db.From<T>().ToTable(); } /// <summary> /// 得到所有的数据 /// </summary> /// <returns>List<T></returns> public virtual List<T> Get_AllData_List() { return db.From<T>().ToList(); } /// <summary> /// 得到top的几条数据 /// </summary> /// <param name="top"></param> /// <param name="where"></param> /// <param name="orderby"></param> /// <returns></returns> public virtual List<T> Get_Entitys_ByTop(int top, WhereClip where, OrderByClip orderby, params Field[] fields) { if (top == 0) throw new Exception("top值不能为0"); return db.From<T>() .Where(where) .Select(fields) .GetTop(top) .OrderBy(orderby) .ToList(); } #endregion #region "更新" /// <summary> /// 更新一条记录 /// </summary> /// <param name="entity"></param> /// <returns></returns> public virtual bool Update_Entity(T entity) { entity.Attach(); return db.Save<T>(entity) > 0; } /// <summary> /// 通过多个条件更新对象 /// </summary> /// <param name="fields"></param> /// <param name="values"></param> /// <param name="where"></param> /// <returns></returns> public virtual bool Update_Entity_byWhere(Field[] fields, object[] values, WhereClip where) { return db.Update<T>(fields, values, where) > 0; } /// <summary> /// 通过单个条件更新对象 /// </summary> /// <param name="fields"></param> /// <param name="values"></param> /// <param name="where"></param> /// <returns></returns> public virtual bool Update_Entity_byWhere(Field filed, object value, WhereClip where) { return db.Update<T>(filed, value, where) > 0; } #endregion #region "删除" /// <summary> /// 通过对象删除记录 /// </summary> /// <param name="entity"></param> /// <returns></returns> public virtual bool Delete_Entity(T entity) { return db.Delete<T>(entity) > 0; } /// <summary> /// 通过主键ID集合删除 /// </summary> /// <param name="idList"></param> /// <returns></returns> public virtual int Delete_Entitys(List<string> idList) { return Delete_Entitys(idList.ToArray()); } /// <summary> /// 通过主键ID集合删除 /// </summary> /// <param name="idList"></param> /// <returns></returns> public virtual int Delete_Entitys(string[] idList) { return db.Delete<T>(idList); } /// <summary> /// 通过条件删除对象 如果批量删除可以传入条件 where = T.ID.in(obj[]) /// </summary> /// <param name="where"></param> /// <returns></returns> public virtual bool Delete_Entity(WhereClip where) { return db.Delete<T>(where) > 0; } #endregion #region "新增" /// <summary> /// add an new record, /// </summary> /// <param name="entity"></param> /// <returns></returns> public virtual bool Add_Entity(T entity) { return db.Save<T>(entity) > 0; } #endregion #region "分页" /// <summary> /// 分页显示数据 需要记录总数 /// </summary> /// <param name="currentPageindex">当前页码</param> /// <param name="pageSize">pagesize</param> /// <param name="where">WhereClient</param> /// <param name="orderby">OrderByClip</param> /// <param name="record">总的记录数</param> /// <returns></returns> public virtual List<T> Get_Entity_byPage(int currentPageindex, int pageSize, WhereClip where, OrderByClip orderby, out int record, params Field[] fields) { record = Get_Entity_Record(where); return Get_Entity_byPage(currentPageindex, pageSize, where, orderby, fields); } /// <summary> /// 分页 返回Datatable /// </summary> /// <param name="currentPageindex"></param> /// <param name="pageSize"></param> /// <param name="where"></param> /// <param name="orderby"></param> /// <param name="record">总记录</param> /// <param name="fields"></param> /// <returns></returns> public virtual DataTable Get_Entity_byPage_ToTable(int currentPageindex, int pageSize, WhereClip where, OrderByClip orderby, out int record, params Field[] fields) { record = Get_Entity_Record(where); return Get_Entity_byPage_ToTable(currentPageindex, pageSize, where, orderby, fields); } /// <summary> /// 通过条件得到表的记录数 /// </summary> /// <param name="where"></param> /// <returns></returns> public virtual int Get_Entity_Record(WhereClip where) { return db.From<T>().Where(where).Count(); } /// <summary> /// 分页显示数据 不需要记录总数 /// </summary> /// <param name="currentPageindex">当前页码<</param> /// <param name="pageSize">pagesize</param> /// <param name="where">WhereClient</param> /// <param name="orderby">OrderByClip</param> /// <returns></returns> public virtual List<T> Get_Entity_byPage(int currentPageindex, int pageSize, WhereClip where, OrderByClip orderby, params Field[] fields) { return db.From<T>() .Where(where) .Select(fields) .OrderBy(orderby) .GetPage(pageSize) .ToList(currentPageindex); } /// <summary> /// 分页返回Datatable /// </summary> /// <param name="currentPageindex"></param> /// <param name="pageSize"></param> /// <param name="where"></param> /// <param name="orderby"></param> /// <param name="fields"></param> /// <returns></returns> public virtual DataTable Get_Entity_byPage_ToTable(int currentPageindex, int pageSize, WhereClip where, OrderByClip orderby, params Field[] fields) { return db.From<T>() .Where(where) .Select(fields) .OrderBy(orderby) .GetPage(pageSize) .ToTable(currentPageindex); } #endregion #region "批量处理" /// <summary> /// 带事物的批量添加 /// </summary> /// <param name="entityList"></param> /// <returns></returns> public virtual bool BatchAdd_Entitys(List<T> entityList) { //使用事务进行批量数据插入 using (DbTrans trans = db.BeginTrans()) { try { DbBatch batch = trans.BeginBatch(entityList.Count); entityList.ForEach(item => { item.Detach(); batch.Save(item); }); batch.Process(); trans.Commit(); return true; } catch { trans.Rollback(); return false; } } } /// <summary> /// 批量更新 /// </summary> /// <param name="entityList"></param> /// <returns></returns> public virtual bool BatchUpdate_Entitys(List<T> entityList) { //使用事务进行批量数据更新 using (DbTrans trans = db.BeginTrans()) { try { DbBatch batch = trans.BeginBatch(entityList.Count); entityList.ForEach(item => { item.Attach(); batch.Save(item); }); batch.Process(); trans.Commit(); return true; } catch { trans.Rollback(); return false; } } } #endregion }
1.由于MySoft可以动态传入DbSession对象来支持不通的数据库操作,这里给先前的BaseDao类添加了一个带DbSession的构造函数,2.所有方法改成虚方法,使继承类可以重写自己的实现.在数据的业务逻辑操作类中,修改如下:
namespace Ecom.BusinessLogic.EshopManageMent { public partial class e_ShopService : BaseDao<e_Shop> { #region "ctor" //这里有多个数据库的操作情况,传入相应的数据库操作对象 public e_ShopService() : base(DataAcess.DefaultSession) { } #endregion } }
DaAcess 类如下:因为我这个项目有对多个数据库的操作,所以配置如下
public static class DataAcess { /// <summary> /// 通过配置节来实例化DbSession /// </summary> public static readonly DefaultSession DefaultSession = new DefaultSession(); /// <summary> /// API基础数据库 /// </summary> public static readonly DbSession TopSession = new DbSession("TopDataBaseCon"); /// <summary> /// 跟踪基础库 /// </summary> public static readonly DbSession TrackSession = new DbSession("TrackingCon"); } public class DefaultSession : DbSession { public DefaultSession() : base("ApplicationServices")
{ this.RegisterSqlLogger(log => { //输出调试信息 ComLib.Debug.DebugView.PrintDebug(log); }); } }
二.项目规划
以Eshop模块为例,e_shop文件是mysoft生成的实体类,e_ShopService是生成的一般关系处理业务逻辑类(关系查询),e_ShopPartial是自己写的业务特殊业务处理类,2个类都是部分类,这样的分开是为了在让自己写的东西和生成的东西隔离,修改表结构或生成设置的时候不影响到现有代码。这里的命名规则如下,在eshop模块以下,全部的命名空间为
Ecom.BusinessLogic.EshopManageMent,使得我们处理的逻辑关注于模块的处理。
为什么要把CommonLibraries独立出一个文件夹,个人原因呢,因为东西是我写的,我希望调试的某些时候直接跟入源码,对源码BUG进行修改或者增加功能,如果是队友开发,将会把这些类库编译好的DLL全部放入Dependencies,Dependencies文件夹是为了让大家对项目依赖的DLL一目了然。
三.使用IOC,SingletonProvider来管理我们的业务逻辑
1.为什么引入IOC: 在项目中,随处出现 logic a = new logic(); 这样的调用,每次调用一次业务,就要new一个实例出来,或者干脆在每个调用的类中写一个类全局变量,让全局调用,虽然这样的写法没问题,但是我觉得对于这种不需要保存状态的类,应该集体的进行管理,也不需要每次通过new得到实例,我的做法如下:
IOC类的来源是:CommonLibrary.NET 中IOC模块
2.为什么引入SingletonProvider,对于所有仅限于单线程操作的类,不需要去在每个类中去写相同的得到单列代码
public class PageServiceBase : Page { #region "通过容器获取类型实例" public e_ShopService MyEshopService { get { return Ioc.GetObject<e_ShopService>("e_ShopService"); } } public e_IspService MyIspService { get { return Ioc.GetObject<e_IspService>("e_IspService"); } } #endregion #region SingerInstance 如果类是单列模式 那么使用通用的 SingletonProvider获取实例 //public e_ShopService MyInstanceShopService { // get { // return SingletonProvider<e_IspService>.Instance; // } //} #endregion }
好吧,现在我所有继承这个page类的页面,要调用业务逻辑类只需要写 this.MyIspService.XXX();就OK了,清爽,方便,集中管理....
别忘记了,在Global文件中注册业务类.
protected void Application_Start(object sender, EventArgs e) { Ioc.Init(new IocContainerInMemory()); Ioc.AddObject("e_ShopService",new e_ShopService()); Ioc.AddObject("e_IspService", new e_IspService()); }