在ASP.NET MVC控制器中管理Entity Framework ObjectContext的依赖注入的正确方法是什么?

时间:2012-04-26 22:57:42

标签: entity-framework dependency-injection inversion-of-control

在我的MVC控制器中,我使用的是IoC容器(Ninject),但在实体框架ObjectContext中,我不确定如何最好地使用它。

目前,我正在做类似的事情:

using(var context = new MyObjectContext())
{
     var stuff = m_repository.GetStuff(context);
}

从最简单的时间保持数据库连接开放的角度来看,这是管理的最佳方式。

如果我是基于每个请求通过Ninject创建ObjectContext,这显然会使数据库连接保持打开状态太长时间。

上面的代码也会变成......

var stuff = m_repository.GetStuff(m_myObjectContext);

(我什么时候处理上下文......?)

我应该为ObjectContext创建一个工厂并通过DI传递它吗?这会松开耦合,但是如果没有简单的方法来维护ObjectContext的接口(我知道的话),这对可测试性有帮助吗?

有更好的方法吗?感谢

1 个答案:

答案 0 :(得分:3)

  

这是保持最佳管理方式的最佳方式   数据库连接在最短的时间内打开。

     

如果我是按每个请求通过Ninject创建ObjectContext   基础上,这显然会使数据库连接保持打开状态太长时间。

实体框架将在执行每个查询后直接关闭连接(除了从外部提供打开的连接时),因此您执行此类操作的参数不成立。

过去我曾经通过业务逻辑(我的command handlers来确切)控制上下文(创建,提交和处理它),但缺点是你需要传递这个所有其他方法和所有依赖项的上下文。当应用程序逻辑变得更复杂时,这会导致代码的可读性和可维护性降低。

出于这个原因,我转移到了一个模型,在该模型中,工作单元(您的MyObjectContext)被创建,提交并处置在业务逻辑的控制范围之外。这允许您将工作单元注入所有依赖项,并为所有对象重用相同的工作单元。缺点是,这会使您的DI配置更加困难。您需要确定的一些事项:

  1. 必须根据网络请求或在特定范围内创建工作单元。
  2. 工作单元必须在请求或范围的末尾处理(尽管在DbContext未处理时可能不是问题,因为欠照连接已关闭且DbContext确实没有实现终结者。)
  3. 您需要明确提交工作单元,但是您不能在Web请求结束时执行此操作,因为此时您不知道提交是否安全(因为您没有&#39 ; t想要在业务逻辑引发异常时提交,但在请求结束时无法正确检测这是否真的发生了。)
  4. 我可以给你的一个提示是在command handlers周围对系统中的业务逻辑进行建模,因为这允许你定义一个处理事务行为的装饰器(提交工作单元甚至可能运行所有内容)在一个数据库事务中)在一个点上。这个装饰器可以包裹在系统中的每个处理程序中。

    我必须承认我不知道如何使用Ninject注册泛型类型和泛型装饰器,但是当你在Stackoverflow上询问时,你可能会很快得到答案。