回到目錄
在之前寫的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的構造方法注入。
作者:倉儲大叔,張占嶺,
榮譽:微軟MVP
QQ:853066980
支付寶掃一掃,為大叔打賞!
