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(); 
}