【问题标题】:How to pass ApplicationDbContext to ASP.NET MVC5 constructor?如何将 ApplicationDbContext 传递给 ASP.NET MVC5 构造函数?
【发布时间】:2015-06-03 20:03:01
【问题描述】:

在我的 ASP.NET MVC 应用程序中,所有控制器都使用这个 ApplicationDbContext 对象。目前它正在控制器构造函数中实例化,但这是紧密耦合的,不是一个好的做法。

    public MessagesController()
    {
        this.Db = new ApplicationDbContext();
        this.Mapper = new MessageMapper(Db);
        this.Service = new MessageService();
    }

理想情况下,我希望将此 ApplicationDbContext 作为参数传递给每个控制器的构造函数,就像这种依赖注入的场景:

public MessagesController(ApplicationDbContext context){
    this.Db = context;
    this.Mapper = new MessageMapper(Db);
    this.Service = new MessageService();
}

问题是,如何做到这一点?我试图找到控制控制器依赖注入的源代码,但它以 .NET dll 文件的形式出现,我无法修改(就像您无法编辑系统命名空间文件一样)。那么,ASP.NET MVC 中的控制器如何进行依赖注入呢?谁能以我的场景为例?谢谢。

【问题讨论】:

  • 有许多带有 MVC 适配器的 IoC 框架。请参阅 asp.net/mvc/overview/older-versions/hands-on-labs/… 了解 Unity
  • 实际上您也想将服务作为依赖项传递。如果 Mapper 实际上是一个 Repository,那么它应该被注入而不是 ApplicationDbContext,它是一个 persistence detail。顺便说一句,正确使用 DI 意味着您只向构造函数注入您需要的服务(存储库也是一种服务),而不是自己做事所需的所有依赖项。
  • 感谢您的建议。我还想知道,如果我想将 Controller.Server 之类的东西注入到一个名为 ImageUploadService 的类中,我该怎么做?问题是 Controller.Server 在控制器的构造函数中不可用,而仅在控制器操作中可用。我想确保作为依赖项传递的 Controller.Server 始终是同一个实例。

标签: c# asp.net asp.net-mvc dependency-injection asp.net-mvc-5


【解决方案1】:

安装这个包:

Install-Package Unity.Mvc5 

在你的 Application_Start() 中添加这一行:

protected void Application_Start()
  {
    AreaRegistration.RegisterAllAreas();
    UnityConfig.RegisterComponents();                           // <----- Add this line
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
  }  

在 UnityConfig 中注册您的类型:

container.RegisterType<ApplicationDbContext>();

完成。

更新 顺便说一句,通过这样做,您只需将创建新对象的代码移动到 Unity。购买你还在等待具体的类。此外,您将在控制器中进行所有数据操作操作(阅读:UI)。如果你真的想摆脱紧密耦合,你可能想看看 DAO 模式。 http://en.wikipedia.org/wiki/Data_access_object

【讨论】:

  • 感谢您的建议。所以 Unity 就像一个依赖注入容器? container.RegisterType() 背后的魔力是什么?当一个类请求这个依赖时,它会创建一个 ApplicationDbContext 对象吗?
  • 也有问题。 ASP.NET MVC5 控制器带有 dispose 方法,该方法在控制器垃圾回收时释放 ApplicationDbContext 对象。如果控制器甚至不知道 ApplicationDbContext,我该如何重构这个 Controller.Dispose()\ 方法?我可以将逻辑移动到 Repository 并改为调用 Repository.Dispose() 吗?
【解决方案2】:

我会告诉你我的方法。

首先,您不希望 DBContext 直接暴露给控制器。事实上,要真正分离关注点,您根本不希望控制器知道DbContext

如果您得知公司计划开始使用不同的存储技术,例如 RavenDBMongoDB,则您的控制器的每一个都需要重构. DbContext 不是必需的或有用的。

我不知道MessageMapper 类是什么,但它确实需要DbContext,而且它也会中断。

您需要考虑采用存储库模式

阅读这篇文章,它应该会有所帮助。

http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

【讨论】:

  • 是的,这正是我现在想要的。我正在重构应用程序,并将 Repository 和 Mapper 传递给控制器​​构造函数,将来完全没有 ApplicationDbContext。由于历史原因,Mapper 在构造函数中采用 DbContext,这很糟糕,因为 Mapper 只应该在 Model 和 ViewModel 之间进行映射,而不是访问数据库中的数据。这就是我使用 Repository 模式重构的原因。感谢您的提示。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-14
  • 1970-01-01
  • 1970-01-01
  • 2015-12-18
  • 2012-10-29
相关资源
最近更新 更多