C# 在释放DbContext时使用EntityFramework导航属性

C# 在释放DbContext时使用EntityFramework导航属性,c#,entity-framework,idisposable,dbcontext,C#,Entity Framework,Idisposable,Dbcontext,“我的服务类”(在ASP.NET MVC应用程序中)中的当前检索模式类似于: public Client Get(int id) { using (var repo = _repoFactory.Get<Client>()) { return repo.Get(id); } } 公共客户端获取(int-id) { 使用(var repo=\u repoFactory.Get()) { 返回回购获取(id); } } 其中\u repoFac

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

public Client Get(int id)
{
    using (var repo = _repoFactory.Get<Client>())
    {
        return repo.Get(id);
    }
}
公共客户端获取(int-id)
{
使用(var repo=\u repoFactory.Get())
{
返回回购获取(id);
}
}
其中
\u repoFactory.Get()
返回一个存储库,当该存储库被释放时,还将释放实体框架
DbContext

但是,当
Get(int id)
方法的使用者需要在
客户机
对象上使用导航属性时,会引发异常,因为上下文已被释放

我可以预见一些解决这个问题的方法:

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

什么是“正确的”(或至少是不正确的)方法以及如何实现它?

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

不要在服务之外使用导航属性 如果服务返回实体,则很难执行此操作。在我当前的项目中,我们大量使用了“DTO”,这是一种新的类,表示我们在给定上下文中预期需要的数据。因为它们不是实体,所以我们知道它们上的任何属性在从存储库返回之前都会被完全水合

不要使用延迟加载导航属性 这与上面的内容大致相同,只是允许加载某些导航属性。同样,使用这些数据的开发人员如何知道哪些属性可用,哪些属性不可用?“DTO”解决了这个问题,但它们也引入了一系列与现有实体几乎相同的额外类

当请求完成时,寻找其他方法来处理上下文 通常,人们通过将上下文绑定到DI框架中的每个请求范围中来实现这一点,并允许DI框架负责上下文的实例化/处理

这种方法的主要危险在于,虽然延迟加载属性在访问时不会抛出异常,但每次访问都需要另一个数据库往返。这使得开发人员很容易意外地编写代码,而如果不这样做,则只需要两到三次往返就可以完成数千次往返


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

谢谢-我认为我不会得到比这更好的答案。对于遇到这个问题的人,我选择了第三个选项—使用Castle Windsor控制db上下文的生存期(
LifetimePerHttpRequest()