EF中使用UnitOfWork

一、前言

      每次提交数据库都会打开一个连接,造成结果是:多个连接无法共用一个数据库级别的事务,也就无法保证数据的原子性、一致性。解决办法是:在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层的方法才能实现对数据的完成操作。

猜你喜欢

转载自www.cnblogs.com/masonblog/p/9565073.html