我有一个服务,一个存储库和一个DbContext
。存储库拥有DbContext
,服务拥有存储库。
我的存储库应该实现IDisposable
吗?如果是这样,我的服务是否也应该实现IDisposable
并处置存储库?
我想一个更普遍的问题可能是,如果我有一个类有一个类的引用,它有一个对另一个类的引用,...(等等)...,它有一个引用非托管或托管的可支配资源 - 他们所有实施IDisposable
吗?
答案 0 :(得分:3)
Unity DI没有办法在生命周期结束时处理对象,并且在GC决定收集它们之前你不能将它们留在那里。
理论上有DI框架实现了Register / Resolve / Release,而Release将是调用dispose的地方,但Unity并没有实现Release部分。我不知道是否还有其他框架可以在.NET中执行此操作。
使用Unity,有两种解决方案:
不要注入DbContext,但要在您需要的地方从容器中解析它,以便您可以控制它的处置
using(var ctx = container.Resolve<MyDbContext>())
{
}
<强> ALARM!报警!服务定位器反模式
在您需要时注入可以为您提供DbContext的工厂。如果你这样做,而不是注入一个DbContext,你可以注入一个类,它可以在你需要时为你提供DbContext:一个工厂。您可以将工厂注册为DI容器中的单件,因为您将连续使用它
using(var ctx = DbContextFactory.GetContex())
{
}
你的工厂看起来像这样:
public class DbContextFactory : IDbContextFactory
{
public DbContext GetDbContext()
{
...
}
}
因此可以通过构造函数注入注入:
public MyService(IDbContextFactory dbContextFactory)
{
}
并且,正如所解释的那样,没有理由不将其注册为单身人士:您可以安全而愉快地使用相同的工厂来构建大量的Db上下文!
注意:如果你使用一个抽象工厂会好得多,而不是返回具体对象返回一个接口实现,这是一个小小的改变
public class DbContextFactory : IDbContextFactory
{
public IDbContext GetDbContext()
{
...
}
}
您可以阅读此内容以获取更多信息和样本:
答案 1 :(得分:2)
就IDisposable而言,我认为如果一个对象实现了IDisposable,你需要处理它,即使有些例子没有调用IDisposable也不会导致任何问题。但这是一个实施细节,依赖它可能不安全(与IDisposable合同相反)。
您没有提及您正在使用的服务类型,但您确实提到您使用的是Unity。
如果是Web API服务,您可以使用Unity bootstrapper for ASP.NET Web API(以及Unity bootstrapper for ASP.NET MVC。这会产生一个PerRequestLifetimeManager,每个请求会给出一个单例(不确定)如果您需要或不需要,但这是常见的情况。)
此外,还安装了IHttpModule,UnityPerRequestHttpModule,它将在HTTP请求结束时(使用PerRequestLifetimeManager注册)处理IDisposable对象实例。
如果使用其他服务堆栈(例如WCF),那么您可以自己实施类似的东西,或者使用JotaBe答案中概述的工厂方法。