首先,让我们看看微软对Asp.Net Core默认的依赖注入服务的看法:
该框架负责创建依赖项实例,并在不再需要它时将其处理。
即该框架将调用一个类Dispose方法(假设该类实现IDisposable)
第二,DbContext类确实确实实现了IDisposable。
第三,在我们的Startup.cs类中,我们通过AddDbContext方法添加了DbContext,该方法默认情况下被添加为Scoped实例(即,我们的DbContext被创建并针对每个单个请求进行垃圾回收) )。
范围内的生命周期服务每个请求创建一次。
例如
public void ConfigureServices(IServiceCollection services)
{
services
.AddDbContext<TheStoreDbContext>(ConfigureDbContext)
.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
}
结论,我们不需要在Asp.net Core应用程序中的任何位置显式调用context.Dispose()。
那么为什么在线上和教程中有那么多示例向您显示必须在Repository或UnitOfWork类中实现IDisposable?
例如
public class UnitOfWork : IUnitOfWork
{
private readonly DbContext _context;
public IProductRepository ProductRepository { get; }
public UnitOfWork(DbContext context)
{
_context = context;
ProductRepository = new ProductRepository(context);
}
public void Dispose()
{
_context.Dispose();
}
}
您怎么看?这是一个有效的问题吗?不在任何地方显式调用Dispose()方法是否有意义?
答案 0 :(得分:4)
您的UnitOfWork
类示例实际上是一种不好的做法。规则是,一个类只能处置其拥有的。但是,对于UnitOfWork
,它不是拥有 DbContext
,因为它不是由UnitOfWork
创建的,而是由其他人提供的。 / p>
留下UnitOfWork
来处理DbContext
甚至是有问题的,因为UnitOfWork
无法得知DbContext
是否在系统中的其他类仍在使用时UnitOfWork
被处置。换句话说,当UnitOfWork
开始处理该依赖项时,系统可能会崩溃。
因此,如果您遵循只处置自己拥有的物品的规则,这意味着UnitOfWork
实际上应该不完全实现IDisposable
。这意味着您让“其他人”控制DbContext
的生存期。
将对依赖项生命周期(例如DbContext
)的控制权移交给第三方的想法并不是什么新鲜事物,当然也不是新Microsoft DI容器所特有的。实际上,这是一个古老的想法,即您在应用程序的启动路径中集中控制应用程序组件的生命周期。在DI的上下文中,该启动路径通常称为Composition Root。
在“合成根目录”内部, Composer 的工作是创建应用程序组件,管理其生命周期并在不再需要它们时进行处理。 DI容器(如.NET Core DI容器)在您的系统中充当Composer,但您也可以手动完成此操作-这种做法通常称为Pure DI。