一、前言
每次提交数据库都会打开一个连接,造成结果是:多个连接无法共用一个数据库级别的事务,也就无法保证数据的原子性、一致性。解决办法是:在ObjectContext的CRUD操作基础上再包装一层,提供统一的入口,让服务层调用。同一个UnitOfWork实例对象下所有的ObjectContext都共同一个数据库上下文对象(ps:EF用的是ObjectContext),也就是共用一个事物。提交数据库时,只要有一个操作失败,那么所有的操作都被视为失败。
实际使用:https://www.cnblogs.com/masonblog/p/9563199.html
代码托管:https://github.com/catbiscuit/AutofacStudy
二、实现
1、Apps.Model
(1)项目截图
(2) 创建edmx文件。
删除其中的两个.tt文件,然后在edmx页面,右键点击属性,将属性中的代码生成策略 从"无"修改为"默认值"。
2、Apps.Infrastructure 基础设施层。
(1)项目截图
(2)详细代码在GitHub上下载代码查看,贴出来篇幅过多。
3、使用。以Teacher表为例,实体类为Teacher.cs。
(1)IDAL层。
直接继承IDALBase<T>泛型接口,其中定义了一些基础的方法。
namespace Apps.IDAL { public interface ITeacherDAL : IDALBase<Teacher> { } }
(2)DAL层
直接继承DALBase<T>类,和ITeacherDAL接口。
DALBase类,需要提供实体类和数据库上下文。因为需要创建一个统一管理数据库操作的对象。
namespace Apps.DAL { public class TeacherDAL : DALBase<Teacher, AutofacDBEntities>, ITeacherDAL { public TeacherDAL(IDatabaseFactory<AutofacDBEntities> databaseFactory) : base(databaseFactory) { } } }
(3)IBLL层。
定义基本的数据操作方法。
namespace Apps.IBLL { public interface ITeacherBLL { bool Add(Teacher entity); bool Delete(Teacher entity); bool Update(); Teacher GetModelByCondition(Expression<Func<Teacher, bool>> predicate); IQueryable<Teacher> GetList(Expression<Func<Teacher, bool>> predicate, Expression<Func<Teacher, object>> orderBy, bool isAscending); IQueryable<Teacher> GetList(Expression<Func<Teacher, bool>> predicate); Teacher GetModelBySql(string sql); } }
(4)BLL层。
对ITeacherBLL接口中方法的实现。
注意:
第一:类中定义了一个IUnitOfWork泛型对象,这个就是单元事务的管理对象。
DAL层只是将对数据的操作,添加到一个数据缓存的集合中。
当数据操作的步骤完成时,才调用IUnitOfWork泛型对象进行数据操作的提交。
这样确保了原子性和一致性。
第二:Update操作,BLL并没有将数据的操作添加到数据缓存的集合中。
此处,可以通过单步调试,当执行到UnitOfWork类中时,
监视DataContext对象的值,这个对象会监视数据库上下文中数据的状态。
这个地方,就要求Update操作的对象只能是从数据库获取得来。
示例操作:
Model model = DAL.GetModel();
model.Name = "修改Name";
BLL.Update();
此时BLL层执行update方法,实际上只是执行了单元事务的提交,也就完成了对该条记录的修改。
所以,如果是实例化的对象是无法修改数据。
Model model = new Model();
model.ID = "2";
model.Name = "修改Name";
BLL.Update();
这样执行更新操作,是无法真正修改数据的。
namespace Apps.BLL { public class TeacherBLL : ITeacherBLL { private readonly ITeacherDAL _iTeacherDAL; private readonly IUnitOfWork<AutofacDBEntities> _uwork; public TeacherBLL(ITeacherDAL iTeacherDAL , IUnitOfWork<AutofacDBEntities> uwork) { this._iTeacherDAL = iTeacherDAL; this._uwork = uwork; } public bool Add(Teacher entity) { _iTeacherDAL.Add(entity); return _uwork.Commit() > 0; } public bool Delete(Teacher entity) { _iTeacherDAL.Delete(entity); return _uwork.Commit() > 0; } public bool Update() { return _uwork.Commit() > 0; } public Teacher GetModelByCondition(Expression<Func<Teacher, bool>> predicate) { return _iTeacherDAL.GetModelByCondition(predicate); } public IQueryable<Teacher> GetList(Expression<Func<Teacher, bool>> predicate , Expression<Func<Teacher, object>> orderBy , bool isAscending) { return _iTeacherDAL.GetList(predicate, orderBy, isAscending); } public IQueryable<Teacher> GetList(Expression<Func<Teacher, bool>> predicate) { return _iTeacherDAL.GetList(predicate); } public Teacher GetModelBySql(string sql) { return _iTeacherDAL.GetModelBySql(sql); } } }
4、总结
DAL层,只是将数据的操作(新增修改删除)附加到数据库上下文中。
UnitOfWork,才是将数据进行提交的地方。
所以,BLL层的方法才能实现对数据的完成操作。