将 DBContext 与依赖注入一起使用的后果
本文关键字:后果 一起 注入 DBContext 依赖 | 更新日期: 2023-09-27 18:32:38
我仍然不熟悉使用依赖注入在我正在编写的 ASP.NET MVC 应用程序中管理我的 DBContext。
我正在尝试遵循文章在 MVC 中管理实体框架 DbContext 生存期 ASP.NET 概述的方法。基本上,这种方法说使用 Ninject 和依赖注入,并将我的 DBContext 作为参数添加到控制器中的构造函数中。
此外,我正在基本控制器中实现这一点,或者我的所有控制器类都将派生。
这是有效的,但我遇到了以下问题。
此方法要求每个派生控制器类还实现一个构造函数,该构造函数接受我的控制器基类所需的任何参数。这不仅看起来像是我必须记住添加到任何新的派生类中的大量额外类型,而且还意味着如果我更改传递给构造函数的数据,则必须修改每个派生控制器类中的构造函数。
这为我提供了所有控制器类的DBContext。但是我的模型中需要DBContext的其他类呢?我是否需要手动将实例传递给 DBContext 到所有这些类?或者有没有办法为每个类使用 DI 来获取它们自己的 DBContext 副本?
此方法要求每个派生控制器类还 实现一个构造函数,该构造函数接受我的 控制器基类。这不仅看起来很多额外的东西 我必须记住添加到任何新的派生类中的键入,但是它 也意味着如果我更改传递给构造函数的数据,那么我 必须修改每个派生控制器类中的构造函数。
这是您可以选择在应用程序中使用 EF 的方法之一(重型控制器(,IMO 它不是最干净的方法。你正确地注意到了自己的缺点。
如果我们将这种方法与设计原则联系起来,它就会打破单一责任原则,因为控制器应该做更多的事情(获取或更新DB(,而不仅仅是收集数据并返回包含数据的适当视图。那么业务规则呢,控制器会应用它吗,如果您需要发送电子邮件,控制器也会这样做吗?您应该有另一层专门为一组需求而设计的业务/服务类,例如EmailHelper会发送电子邮件。
它还破坏了打开关闭原则,因为每次更改输入参数时都需要更改构造函数。
这为我提供了所有控制器类的DBContext。但是什么 关于我的模型中需要DBContext的其他类?我是否需要 手动将实例传递给 DBContext 到所有这些类?
就依赖注入而言,目标之一是将依赖注入到直接需要的地方。如果你有一个需要 DbContext 的模型类,你应该在模型类构造函数中注入它(大多数 DI 框架也支持属性注入,但构造函数仍然是最喜欢的方法(。
使用 DI Framework,您将在一个位置配置依赖项(应用程序初始化代码(,然后每个需要依赖项的类只需在构造函数中接受它。
DI 容器可以与字典进行比较,其中键是接口,值是熟对象。设置完成后,您可以随时在整个应用程序中使用正确的键来请求任何对象。
或者有没有办法为每个类使用 DI 来获取自己的 DBContext的副本?
DI 框架支持不同的实例化方式,以允许控制实例的生存期。通常,按请求、按线程和单一实例。更多信息在这里。如果希望每个控制器获取 DbContext 的副本,则可以在设置 DbContext 实例化时使用每个请求配置。
替代解决方案:
我的大多数MVC应用程序都有一个服务层(应用业务规则的类集(。这些类中的每一个都注入了 DbContext(不完全是 DbContext,而是 IDataContext(。控制器注入了检索或更新数据所需的服务类。
抽象了 IDataContext 背后的 DbContext,我可以在我的测试中设置一个存根数据上下文,或者明天如果我想从 EF 切换到 NHibernate 或更智能的 DI 框架,我只需要实现 IDataContext 并更改依赖项初始化代码。
希望这有帮助。