文章出處

回到目錄

在之前寫的DDD~基礎設施層文章中,提到了UnitOfWork,它里面有一些方法,但經過項目證明,不應該有Save和IsExplicitSubmit,而這個工作單元只起到了數據上下文統一的作用,如A和B對象需要在同一個上下文中工作,這時,我們可以引用工作單元的概念,而對于保存和提交操作,還是應該在局部方法里完成的。

為了不去觸發MSDTC,我會封裝一個特殊的事務,來實現這個工作,而對于SQL2008來說,可以直接使用.net自己的TransactionScope實現,對于同一個數據庫來說,它不會被提升為分布式事務,而SQL2008以下的版本,則需要使用占占封裝的事務,代碼如下:

    /// <summary>
    /// Author:zhang.zhanling
    /// 同步文章:http://www.cnblogs.com/lori/p/3455393.html
    /// 對TransactionScope,讓它對同一個數據庫不產生msdtc服務
    /// </summary>
    public class TransactionScopeNoMsdtc
    {
        /// <summary>
        /// 產生包裹事務
        /// 支持LINQ表提交,并同時返回提交結果到實體
        /// </summary>
        /// <param name="db">數據上下文,多個方法使用的上下文必須是同一個</param>
        /// <param name="isOutermost">是否為最外層,默認為false</param>
        /// <param name="action">處理代碼塊</param>
        public static void UsingNoMsdtc(DbContext db, bool isOutermost, Action action)
        {
            var objectContext = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)db).ObjectContext;
            try
            {
                if (objectContext.Connection.State == System.Data.ConnectionState.Closed)
                    objectContext.Connection.Open();
                using (TransactionScope trans = new TransactionScope())
                {
                    try
                    {
                        action();
                        trans.Complete();
                    }
                    catch (Exception)
                    {
                        throw;
                    }
                    finally
                    {
                        trans.Dispose();
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                if (isOutermost)//如果是最外層事務,而將連接關閉
                {
                    objectContext.Connection.Close();
                }
            }
        }
        /// <summary>
        /// 產生包裹事務,它不是最外層的,如果是最外層的需要調用其它重載
        /// </summary>
        /// <param name="db">數據上下文,多個方法使用的上下文必須是同一個</param>
        /// <param name="action">處理代碼塊</param>
        public static void UsingNoMsdtc(DbContext db, Action action)
        {
            UsingNoMsdtc(db, false, action);
        }
    }

而最新的IUnitOfWork接口就變成了一個標識接口,代碼如下

    /// <summary>
    /// 數據上下文標識接口,它對于業務層應該是公開的
    /// 它對于實現上下文的方法,它并不關心,可以是linq2sql,ef,ado.net,nhibernate,memory,nosql等
    /// </summary>
    public interface IUnitOfWork
    {
    }

我們看到,IUnitOfWork主要作用是標示各個倉儲在同一個上下文當中,或者說,在一個工作單元之中,下面是項目中使用的代碼,我們可以參考一下

    /// <summary>
    /// Point_Info倉儲
    /// </summary>
    /// <remarks>create:cyr_(Ben)_20131128</remarks>
    public class Point_InfoRepository : TsingDa_NewLearningBarRepository<Point_Info>
    {
        #region Constructors
        public Point_InfoRepository() : this(null) { }
        public Point_InfoRepository(IUnitOfWork db) : base(db) { }
        #endregion
    }

我們可以看到,上面的倉儲提供了兩個構造方法的實現,默認為空參,還有一個可以為它傳入一個IUnitOfWork工作單元,本倉儲也支持IoC的構造方法注入。

回到目錄


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()