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層的方法才能實現對數據的完成操作。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM