3

我的服务类(在 ASP.NET MVC 应用程序中)中的当前检索模式类似于:

public Client Get(int id)
{
    using (var repo = _repoFactory.Get<Client>())
    {
        return repo.Get(id);
    }
}

Where_repoFactory.Get<T>()返回一个存储库,该存储库在处置时也会处置实体框架DbContext

但是,当Get(int id)方法的使用者需要在Client对象上使用导航属性时,会抛出异常,因为上下文已经被释放。

我可以预见几种方法来解决这个问题:

  • 不要在服务之外使用导航属性
  • 不要使用延迟加载导航属性
  • 在请求完成时找到其他方式来处理上下文

什么是“正确”(或最不正确)的方式,如何实现?

4

1 回答 1

5

您建议的所有方法都是“正确的”,并且每种方法都有其优点和缺点。您需要决定要使用哪种方法。

不要在服务之外使用导航属性

如果服务返回实体,这很难执行。在我当前的项目中,我们大量使用“DTO”,它们是代表我们期望在给定上下文中需要的数据的新类。因为这些不是实体,所以我们知道它们上的任何属性在从存储库返回之前都将完全水合。

不要使用延迟加载导航属性

这与上面大致相同,除了您允许某些导航属性被预先加载。同样,使用这些数据的开发人员如何知道哪些属性可用和不可用?“DTO”解决了这个问题,但它们也引入了一堆与现有实体几乎相同的额外类。

在请求完成时找到其他方式来处理上下文

通常人们通过在其 DI 框架中将上下文绑定在每个请求范围内来做到这一点,并允许 DI 框架处理其上下文的实例化/处置。

这种方法的主要危险在于,虽然延迟加载属性在访问时不会引发异常,但每次访问都需要另一个数据库往返。这使得开发人员很容易意外地编写最终导致数千次往返的代码,否则只需要两到三个。

但是,如果您有一种可靠的方法来识别和解决性能问题,那么您可以在一般情况下使用这种方法,然后在您认为有必要的地方添加一些急切加载。例如,MiniProfiler可以放在您的前端,并为您提供有关您正在进行的数据库往返的信息,以及当它注意到许多数据库查询实际上相同时的警告。

于 2013-11-13T17:35:16.483 回答