使用DBContext和依赖注入的分歧

时间:2014-12-01 02:12:06

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

在我正在编写的ASP.NET MVC应用程序中使用依赖注入来管理我的DBContext仍然有点新鲜。

我试图遵循文章Managing Entity Framework DbContext Lifetime in ASP.NET MVC中概述的方法。基本上,这种方法说使用Ninject和依赖注入,并将我的DBContext作为参数添加到我的控制器中的构造函数中。

此外,我在基本控制器中实现它,或者我的所有控制器类都将被派生。

这是有效的,但我正在解决以下问题。

  1. 这种方法要求每个派生的控制器类也实现一个构造函数,该构造函数接受我的控制器基类所需的任何参数。这不仅仅是我必须记住添加到任何新派生类的额外输入,但它也意味着如果我更改传递给构造函数的数据,那么我必须修改每个派生控制器类中的构造函数。 / p>

  2. 这为我的所有控制器类提供了一个DBContext。但是我的模型中需要DBContext的其他类呢?我是否需要手动将实例传递给DBContext到所有这些类?或者有没有办法为每个类使用DI来获取自己的DBContext副本?

1 个答案:

答案 0 :(得分:6)

  

这种方法也需要每个派生的控制器类   实现一个构造函数,接受my所需的任何参数   控制器基类。这看起来不仅仅是额外的   键入我必须记住添加到任何新的派生类,但它   也意味着如果我改变传递给构造函数的数据,那么我   必须修改每个派生控制器类中的构造函数。

这是您可以选择将EF用于您的应用程序的方法之一(重型控制器),IMO并不是最干净的方法。你正确地注意到了自己的缺点。

如果我们将这种方法与设计原则联系起来,它会破坏单一责任原则,因为控制器需要做的更多(获取或更新数据库),而不仅仅是收集数据并返回带有数据的适当视图。如果需要发送电子邮件,控制器会应用它来管理业务规则,控制器也可以这样做。您应该有另一层业务/服务类,专门为一组需求而设计,例如: EmailHelper会发送电子邮件。

它还会打破Open Close Principle,因为每次更改输入参数时都需要更改构造函数。

  

这为我的所有控制器类提供了一个DBContext。但是什么   关于我的模型中需要DBContext的其他类?我需要吗?   手动将实例传递给DBContext到所有这些类?

就依赖注入而言,其中一个目标是在需要的地方直接注入依赖项。如果你有一个需要DbContext的模型类,你应该将它注入你的模型类构造函数中(大多数DI框架支持属性注入,但构造函数仍然是最喜欢的方法)。

使用DI Framework,您将在一个位置配置依赖项(应用程序初始化代码),然后每个需要依赖项的类只在构造函数中接受它。

DI容器可以与字典进行比较,其中键是接口,值是熟化对象。设置完成后,您可以随时在整个应用程序中使用正确的密钥来询问​​任何对象。

  

或者有没有办法为每个类使用DI来获得自己的   DBContext的副本?

DI框架支持不同的实例化方法,以允许控制实例的生命周期。通常,每个请求,每个线程和单例。更多信息here。如果希望每个控制器都获得DbContext的副本,则可以在设置DbContext实例化时使用每个请求配置。

替代解决方案:

我的大多数MVC应用程序都有一个服务层(一组应用业务规则的类)。这些类中的每一个都注入了DbContext(不完全是DbContext而是IDataContext)。控制器注入了他们需要检索或更新数据的服务类。

已经抽象出了IDataContext背后的DbContext,我可以在我的测试或明天设置存根数据上下文如果我想从EF切换到NHibernate或更智能的DI框架,我将只需要实现IDataContext并更改依赖关系初始化代码。

希望这会有所帮助。