說說IUnitOfWork~方法完整性與統一提交不沖突


回到目錄

第一講 認識IUnitOfWork,為什么要出現IUnitOfWork接口
第二講 Linq to Sql與EntityFrameworks中的SubmtChanges()發生了什么事
第三講 方法完整性與統一提交不沖突
第四講 DbContext對象的創建應該向BLL層公開
第五講 我的IUnitOfWork+Repository架構
 

    在一個方法中,它一般會做一件事情,這樣的方法在功能上比較清晰,在職責上也很單一(這里的單一是褒義的,呵呵),而它所做的這件事,從頭到尾會把它做完,不會做到一半的功能,這屬於功能上的不完整,這不是我們推薦的。

項目中的代碼:

完整的提交方法:

        protected virtual void SaveChanges()
        {
            if (!iUnitWork.IsNotSubmit)
                iUnitWork.Save();
        }

完整的插入方法:

       public virtual void Add(TEntity item)
        {
            _db.Entry<TEntity>(item);
            _db.Set<TEntity>().Add(item);
            this.SaveChanges();
        }

上面代碼是EF實現的插入,很完善,將實現添加到實體集合,並使用SaveChanges()提交到數據庫,一個完善的數據插入流程完成,但一個問題來了如果我們的

業務操作不只是插入一張表,還有更新另一張表,怎么去實現呢?

       public virtual void Modify(TEntity item)
        {
            _db.Set<TEntity>().Attach(item);
            _db.Entry(item).State = EntityState.Modified;
            this.SaveChanges();
        }

上面為完整的更新動作是上面的代碼,現在有一個假設:

UserRepository類有方法Add,ProductRepository類有方法Modify,這時,這兩個方法進行組織,代碼可能是這樣:

...code

userRepository.Add(user);

userRepository.Modify(product);

...code

      事實上,上面的代碼所執行的過程為:先插入用戶表,提交到SQL數據庫,再更新產品表,再提交到SQL數據庫,這時由於提交兩次,SQL端會產生兩個連接池,而如果兩個方法使用了TransactionScope事務塊,並且SQL服務器與WWW服務器在不同的電腦上,會觸發多於的分布式事務(這是可以避免的),而我們知道,windows的MSDTC(分布式事務)服務是最不靠譜的

如何解決這種情況呢,難道方法不該完整嗎?

什么事情都有解決的辦法,方法的完整性在系統設計上是沒有問題的,但有時,對於一個工作單元中有多個方法時,我們需要把這種完整性升級,將多個方法提升為一個整體,即多個方法的完整性問題,解決這個問題的關鍵在於,你的數據上下文是否為一個,你的submitChanges方法是否為一個。

IUnitWork嶄新的接口規范

    /// <summary>
    /// 工作單元
    /// 提供一個保存方法,它可以對調用層公開,為了減少連庫次數
    /// </summary>
    public interface IUnitOfWork
    {
        /// <summary>
        /// 將操作提交到數據庫,
        /// </summary>
        void Save();
        /// <summary>
        /// 是否不提交到數據庫,這只是在具體的repository類中的SaveChanges方法里用到的
        /// 默認為false,即默認為提交到數據庫
        /// </summary>
        /// <returns></returns>
        bool IsNotSubmit { get; set; }
    }

    /// <summary>
    /// 工作單元
    /// 對泛型類型的支持
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface IUnitWork<T> : IUnitOfWork where T : class { }

看了上面的接口,不用我說,大家也知道其中的含義了,Save()為數據上下文提交,而IsNotSubmit表示是否要提交到數據庫,我們都知道bool類型對象的默認

值不false,所以,默認情況下,Add,Modify這些方法的提交動作都是true,即被提交到數據庫。

我們優化這時上面add與modify的方法如下:

Domain.Core.IUnitOfWork _iUnitWork = new backgroundEntities();
 _iUnitWork.IsNotSubmit=true;
userRepository(user);
productRepository(product); 
_iUnitWork.Save();

OK, 上面的代碼所產生的效果就是,將兩條SQL語句發到SQL端 ,使用一個SQL連接池,不產生MSDTC服務。

回到目錄


免責聲明!

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



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