7

我看到幾個與此有關的問題,但我仍然找不到我要找的答案,所以我發佈了我的問題。如果有另一個問題的答案(我只是沒有看到它),請告訴我。Unit Of Work屬於w/EF4,IoC(Unity)和Repository?

我試圖弄清楚我的UnitOfWork屬於哪裏 - 特別是創建時 - 在使用EF4和Unity時使用Repository模式。

基本上,我有一個服務是用來實現我的業務邏輯。這個服務構造函數需要存儲庫,所以服務被注入我的倉庫。然後該服務使用注入的存儲庫對數據存儲執行操作 - 但是我需要將這些包裝在一個工作單元中。

但是,我的工作單元需要注入EF4上下文(或者,在我的情況下,以及上下文的接口 - IObjectContext)。我不確定應該在哪裏創建UoW並將其注入上下文中。

這裏是我能想到的,其中沒有可能的選項看起來是理想的:

  • 附上UOW在服務的構造,因此具有注入瓦特/工作單位,服務這反過來注入w /我的EF4上下文。但是這似乎是錯誤的,因爲我不希望在存儲庫的每個實例上創建我的UoW。

  • 使用container.Resolve進行按需創建,獲取UoW的一個實例,注入我的EF4上下文。這看起來過度必須不斷地打到IoC容器,而不是已經有權訪問UoW。

  • 將上下文直接注入到服務中,允許我創建一個UoW(上下文)。這看起來很糟糕,因爲我已經將上下文暴露給了服務,並且這應該被隔離到存儲庫。

所以我的問題是,是可以接受的這些方法之一,或有另一種方法,我沒有想到的?

在此先感謝。

回答

12

有可能有幾種方法如何使用這個,所以我會描述一個我覺得有用的方法。

Imho定義UoW的地方在於應用程序邏輯 - 調用業務層(業務服務)的邏輯。原因是UoW應該代表邏輯業務交易 - 應用程序邏輯(或遠程調用時的服務外觀)定義了什麼是邏輯事務。因此,例如在MVC你可以用建築去哪兒每個控制器動作代表一個UOW:

public class MyController : Controller 
{ 
    public MyController(IFirstService firstService, ISecondService secondService, 
    IUnitOfWork unitOfWork) 
    { ... } 

    [HttpPost] 
    public ActionResult SomeAction(Model data) 
    { 
    _firstService.SomeProcessing(data); 
    _secondService.SomeProcessing(data); 
    _unitOfWork.SaveChanges(); 
    return RedirectToAction(...); 
    } 
} 

在這個例子中我控制器上的兩個商業服務depenent和行動呼籲他們兩個 - UOW然後保存雙方的服務進行更改。這就是爲什麼我認爲應該可以在控制器中使用UoW的原因,因爲如果您的應用程序層無法訪問UoW,您將無法從幾個服務調用中組合(重用)您的邏輯(因爲每個可能調用它自己的SaveChanges)。

其他方法是服務門面。門面將是你的業務層的公共接口,它會隱藏服務組合:

_firstService.SomeProcessing(data); 
_secondService.SomeProcessing(data); 
_unitOfWork.SaveChanges(); 

在這種情況下UOW不會被傳遞給控制器​​,但以服務立面和服務門面將被注入到控制器。如果您的業務邏輯將通過Web服務(或其他遠程技術)公開,您一定會使用這種方法。

您必須處理的最後一個問題是將UoW傳遞給服務。服務和UoW被注入控制器(主持人,服務門面或其他),但同時必須將UoW(或ObjectContext)注入到服務中,以便內部使用的存儲庫可以使用它。爲此,您需要正確的IoC生命週期管理器,以便在相同的「請求」內爲所有注入返回相同的實例。在Web應用程序的情況下,你需要PerHttpRequest生命週期管理器(你必須自己實施,因爲Unity不提供它)。

+0

感謝您的留言。這是有道理的,我會在週末嘗試這種方法。我可能會跟進幾個問題,但從概念上講,這聽起來很合理。 – 2011-02-18 16:20:59

1

一種方法是管理這個是使用http://mfelicio.wordpress.com/2010/02/07/managing-the-entity-framework-objectcontext-instance-lifetime-in-wcf-and-sharing-it-among-repositories/中描述的方法該文章實現了用於Wcf服務的ContextManager。對於ASP.NET應用程序,我們可以使用這樣的東西。

public class AspNetDBContextManager<TContext> : IDBContextManager 
    where TContext : IDBContext, new() 
{ 
    #region IDBContextManager Members 

    public IDBContext GetDBContext() 
    { 
     return this.GetOrCreateDbContext(); 
    } 

    private IDBContext GetOrCreateDbContext() 
    { 
     if (HttpContext.Current == null) 
     { 
      throw new InvalidOperationException("Can be used only within ASP.NET applications"); 
     } 

     string dbContextKey = string.Format("__AspNetDBCM__{0}__", HttpContext.Current.GetHashCode()); 

     object dbContext = HttpContext.Current.Items[dbContextKey]; 

     if (dbContext == null) 
     { 
      dbContext = new TContext(); 

      if (dbContext != null) 
      { 
       HttpContext.Current.Items[dbContextKey] = dbContext; 
      } 
     } 

     return dbContext as IDBContext; 
    } 

    #endregion 
} 

public interface IDBContext 
{ 
    object Context { get; } 
} 


public interface IDBContextManager 
{ 
    IDBContext GetDBContext(); 
} 
相關問題