2016-02-07 33 views
1

我知道有很多关于这个话题的文章,但是无论我在哪里看,它对我来说都不是太复杂或不清楚。EF - 管理DbContext的最佳方法?

我的团队首先开发使用Entity框架代码的Web应用程序。我们也使用Autofac进行依赖注入。

目前,数据访问如下所示:

提供给那些不包含EF项目的API:

public class DataService 
{ 
    private IDbContextFactory<MyContext> _factory; 
    private IDataServiceExecutor _dataServiceExecutor; 

    public DataService(IDbContextFactory<MyContext> factory, IDataServiceExecutor executor) 
    { 
     _factory = factory; 
     _dataServiceExecutor = executor; 
    } 

    public void AddItem(Product prod) 
    { 
     using (var context = _factory.Create()) 
     { 
      if (_dataServiceExecutor.AddItem(context, prod)) 
       context.SaveChanges(); 
     } 
    } 
} 

我DataServiceExecutor:

public class DataServiceExecutor 
{ 
    private IRepository<Product> _products; 

    public DataService(IRepository<Product> products...more repositories) 
    { 
     _products = products; 
    } 

    public bool AddItem(DbContext context, Prouduct prod) 
    { 
     try 
     { 
      _products.AddItem(context, prod); 

      return true; 
     } 
     catch(Exception ex) 
     { 
      Log(..) 
      return false; 
     } 
    } 
} 

我所有的库继承这个抽象存储库:

public abstract class EFRepository<T> : IRepository<T> 
{ 
    public void AddItem<T>(DbContext context, T item) 
    { 
     context.Set<T>().Add(item); 
    } 

    . 
    . 
    . 
} 

好事是这样每个事务使用一个上下文。

不好的一面是我的服务方法和我的存储库方法都直接使用上下文。应用程序不是那么大,所以现在方法注入上下文很好,但它可能会变得更大,所以在我看来,注入当前状态的上下文是有问题的。它看起来很糟糕。

也许还有更多的优点和缺点,我是不知道的..

有什么办法,我不熟悉,使数据访问更好?

+0

你可能有更好的运气,询问在http://codereview.stackexchange.com/ – Brandon

回答

0

DataServiceExecutor(本质上是动词)总是拼写设计缺陷。这是一种伪装成类的方法(Execute...)。这些课程的职责不明确,因为他们的职能不可避免地属于其他职位。

与Inversion of Control本身一样伟大的模式的问题是,IoC容器可用于注入任何依赖项。所以他们可以让你创建一个依赖关系和分散责任的纠结,并仍然做一个体面的工作来管理生命周期。它们可能会掩盖你所拥有的生命周期问题。

因此,让我们暂时忽略IoC,如果您拨打DataServiceExecutor.AddItem,请查看您的代码在创建简单对象时的外观。

var product = new Product(); 
var factory = new DbContextFactory<MyContext>(); // Dependencies unknown 
var productRepository = new Repository<Product>(context); 
var executor = new DataServiceExecutor(productRepository); 
var dataService = new DataService(factory, executor); 

dataServiceAddItem方法,你基本上有:

using (var context = _factory.Create()) 
{ 
    executor.AddItem(context, product); 
    context.SaveChanges(); 
} 

如果DataService会收到productRepository代替executor,这一切归结为:

productRepository.AddItem(context, product); 
context.SaveChanges(); 

executor可以取出来容易。它唯一的作用似乎是错误记录。但是,这也可以通过DataService来完成。

但是我们还没有完成。正如你自己所表明的那样,以上下文为参数的这些方法有点尴尬。但现在DataServiceExecutor是出来的图片,它更自然的事:

var product = new Product(); 
var factory = new DbContextFactory<MyContext>(); 
using (var context = _factory.Create()) 
{ 
    var productRepository = new Repository<Product>(context); 
    productRepository.AddItem(product); 

    // And for example 
    var orderRepository = new Repository<Order>(context); 
    orderRepository.AddItem(order); 

    // One SaveChanges call! 
    context.SaveChanges(); 
} 

而且DataService消失了。

现在EFRepository存储其context作为成员变量,并AddItem看起来是这样的:

public void AddItem<T>(T item) 
{ 
    _context.Set<T>().Add(item); 
} 

现在回到国际奥委会。

在国际奥委会的光,你的代码的主要问题是这里面DataService.AddItem

using (var context = _factory.Create()) 

您创建不是由IoC容器管理的环境。它的使用寿命范围仅限于AddItem方法。因此,您必须将其传递到各地,以确保业务事务中的所有内容都使用这一个实例。通过将存储库的依赖关系(上下文)返回给构造器注入,让IoC容器管理上下文的生命周期变得更加容易。

顺便说一句,你说DataService是“供给不包含EF项目API”的一部分。但它在其通用参数中引用MyContext。也许MyContext也是抽象的,我不知道。无论如何,你也可以通过IoC提供这种抽象的实例。

+0

感谢您的详细答案!首先,该服务的确提供了API,Autofac将注入上下文工厂。其次,执行者的目的在于实际执行操作,如果操作成功和/或处理上下文,则服务责任是保存更改。我知道它是丑陋传递上下文,但不知道如何使用依赖注入,以防止它,但保持相同的上下文中每笔交易,我无法从你的回答了解如何注入,要么 –

+0

可以注入它类似于你如何注入工厂等,也就是说通过构造函数注入。我确信有很多关于如何使用Autofac注入上下文的例子。但它可能会改变你的程序流程。我认为这是最大的问题。但是,我向您展示的是使用存储库和上下文的更常见(和多功能)方法。 –

+0

我再次读到您的第一条评论,并且所有内容都是如此正确,摆脱执行者是聪明的,并且依赖存储库并在其ctor中采用上下文。现在我面临另一个大问题,那就是如何在我的startApp中实际注册dbContext对象。它迫使我引用Ef,我真的不喜欢 –

0

我的观点是解决方案没有正确分层。我猜DataService是从外部访问的最高层?

在这种情况下我会改变为以下:

  • 服务获取存储库(或数据层)通过构造注入(然后适当地处理)。服务方法只需要相关参数。
  • 什么是数据层用于?它可以被删除吗?我通常在拥有所有存储库的服务下面有一个数据层。在这种情况下,当服务处理数据层时,数据层可能负责处理所有的存储库。
  • 存储库可以保持原样,但应该通过构造函数注入上下文。
+0

Upadated我的问题在这使它更清晰。如果你可以用代码描述你的答案,也许我会更好地了解 –

相关问题