在上一篇的文章中,那样的封装让开发变的很爽,好吧,我承认这是面向数据库编程的思维。在一个类中,封装了单表的几乎所有操作,我的看法是,因为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());
}