4

我正在开始一个新的 ASP.NET MVC 项目。在我的上一个项目中,最大的代码异味之一是我如何绕过实体框架 DbContext,将其存储在 HttpContext.Current 中,在我的渲染事件中调用 SaveChanges(),并执行各种(可能不合时宜的)相关事情。

假设我的工作单元总是对应一个网络请求。创建 DbContext、将该上下文共享到业务库(例如,负责处理某些工作流活动的 MVC 项目外部的程序集)、将结果模型共享回我的控制器以及保留任何更改的正确方法是什么?

老实说,我对依赖注入了解不多。听起来它应该是相关的,但我看不出它如何在我的控制器和外部程序集中的业务流程之间为我提供一个共享的上下文实例。

如果我只需要控制器中的它,那将很容易。我会坚持使用 HttpContext。但是现在 HttpContext 已经溢出到我的外部库中。我是否只定义一个返回当前 DbContext 的接口,并基于 HttpContext 实现该接口?

希望这很清楚我在问什么,因为我有点迷茫。

4

1 回答 1

3

依赖注入听起来就像你在这里所追求的。我的偏好是 ninject,所以下面是我如何使用 EF 执行此操作的一个示例。

安装 Ninject.MVC3(在 nuget 上可用)

转到\app_start\NinjectWebCommon.cs(由上面的包添加)并将以下内容添加到RegisterServices方法中

kernel.Bind<MyContext>().ToSelf().InRequestScope(); //binding in the context in request scope, this will let us use it in our controllers 

在控制器内部使用上下文如下

public class MyController : ....{
   private readonly MyContext _context;
   public MyController(MyContext context){ _context = context; }
   //Do stuff with _context in your actions
}

这是一个非常简单的示例,您可以尝试随着应用程序的增长(例如 ninject 模块)有很多更好的方法来构建它,但这将展示 DI 的工作原理。

需要注意的几件事,始终确保在 requestscope 中绑定上下文(或更频繁地),因为 DBContext 有一个讨厌的习惯,如果它停留太久,它会增长很多。

在与您也可以注入的外部内容共享方面,例如

public class MyExternalLogic{
    public MyExternalLogic(MyContext context){....}
}

public class MyController : ....{
   private readonly MyContext _context;
   public MyController(MyContext context, MyExternalLogic logic){ _context = context; ...}
   //Do stuff with _context in your actions
}

在上面,相同的 DbContext 实例将用于 MyController 和 MyExternalLogic。Ninject 将处理这两个对象的创建。

还有许多其他可用的 DI 容器可以为您提供非常相似的体验。我强烈推荐 DI,因为它对单元测试能力也有很大帮助。

有关我如何使用 Ninject 构建 MVC 应用程序的更多示例,请查看我在 github 上的一些项目,例如https://github.com/lukemcgregor/StaticVoid.Blog

于 2013-04-27T00:47:43.170 回答