EF中使用UnitOfWork

前言

关于EF5中使用UnitWork,参见另一博文:  https://www.cnblogs.com/masonblog/p/9801162.html

每次提交数据库都会打开一个连接,造成结果是:多个连接无法共用一个数据库级别的事务,也就无法保证数据的原子性、一致性。
解决办法是:在ObjectContext的CRUD操作基础上再包装一层,提供统一的入口,让服务层调用。
同一个UnitOfWork实例对象下所有的ObjectContext都共同一个数据库上下文对象(ps:EF用的是ObjectContext),也就是共用一个事物。
提交数据库时,只要有一个操作失败,那么所有的操作都被视为失败。
实际使用:https://www.cnblogs.com/masonblog/p/9563199.html
代码托管:https://github.com/catbiscuit/AutofacStudy

实现过程

实体层

 

 删除其中的两个.tt文件,然后在edmx页面,右键点击属性,将属性中的代码生成策略 从"无"修改为"默认值"。

 

 

数据访问层

 

Teacher表示例

IDAL层

直接继承IDALBase<T>泛型接口,其中定义了一些基础的方法。

namespace Apps.IDAL
{
    public interface ITeacherDAL : IDALBase<Teacher>
    {
    }
}

DAL层

直接继承DALBase<T>类,和ITeacherDAL接口。
DALBase类,需要提供实体类和数据库上下文。因为需要创建一个统一管理数据库操作的对象。

namespace Apps.DAL
{
    public class TeacherDAL : DALBase<Teacher, AutofacDBEntities>, ITeacherDAL
    {
        public TeacherDAL(IDatabaseFactory<AutofacDBEntities> databaseFactory)
            : base(databaseFactory)
        {

        }
    }
}

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);
    }
}

BLL层

对ITeacherBLL接口中方法的实现。

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);
        }
    }
}

注意

第一:类中定义了一个IUnitOfWork泛型对象,这个就是单元事务的管理对象。

DAL层只是将对数据的操作,添加到一个数据缓存的集合中。

当数据操作的步骤完成时,才调用IUnitOfWork泛型对象进行数据操作的提交。

这样确保了原子性和一致性。

第二:Update操作,BLL并没有将数据的操作添加到数据缓存的集合中。

此处,可以通过单步调试,当执行到UnitOfWork类中时,

监视DbContext对象的值,这个对象会监视数据库上下文中数据的状态。

这个地方,就要求Update操作的对象只能是从数据库获取得来。

使用lambda表达式获取实体。

示例操作:

Model model =  DAL.GetModel(2);

model.Name = "修改Name";

BLL.Update();

此时BLL层执行update方法,实际上只是执行了单元事务的提交,也就完成了对该条记录的修改。

但是,如果是实例化的对象是无法修改数据。

Model model = new Model();

model.ID = 2;

model.Name = "修改Name";

BLL.Update();

这样执行更新操作,是无法修改数据的

总结

DAL层,只是将数据的操作(新增修改删除)附加到数据库上下文中。

UnitOfWork,才是将数据进行提交的地方。

所以,BLL层的方法才能实现对数据的完成操作。

 

posted @ 2018-08-31 11:55  我有我奥妙  阅读(4301)  评论(0编辑  收藏  举报