首先,让我们看看微软对Asp的评价。Net Core的默认依赖注入服务:
框架负责创建依赖项的实例,并在不再需要时处理它。
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1#服务的处理
即,框架将调用一个类Dispose方法(假设该类实现IDisposable)
第二个,DbContext类确实实现了开箱即用的IDisposable。
第三个,在我们的Startup.cs类中,我们通过AddDbContext方法添加我们的DbContext,该方法默认情况下被添加为Scoped实例(即,我们的DbContext是在每个请求上创建和垃圾收集的)。
每个请求创建一次作用域终身服务。
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1使用寿命
例如
public void ConfigureServices(IServiceCollection services)
{
services
.AddDbContext<TheStoreDbContext>(ConfigureDbContext)
.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
}
结论,我们不需要显式调用上下文。Dispose()在我们的Asp.net核心应用程序中的任何位置。
那么,为什么网上和教程中有这么多例子向你展示了你必须在你的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()方法有意义吗?
经验法则是,类应该只处理它所拥有的。然而,在UnitOfWork
的情况下,它并不拥有DbContext
,因为它不是由UnitOfWork
创建的,而是由其他人从外部提供的。
让UnitOfWork
处理该DbContext
甚至可能是有问题的,因为当UnitOfWork
被处理时,UnitOfWork
无法知道系统中的其他类是否仍在使用DbContext
。换句话说,当UnitOfWork
开始处理该依赖关系时,应用程序可能会中断。
因此,如果您遵循仅处理拥有的的规则,则意味着UnitOfWork
实际上不应该实现IDisposable
。这意味着你让"其他人"控制DbContext
的寿命。
将依赖项(如DbContext
)的生存期控制权转移到第三方的想法并不是什么新鲜事,当然也不是新的Microsoft DI容器特有的。这实际上是一个古老的想法,即在应用程序的启动路径中集中控制应用程序组件的生命周期。在DI的上下文中,此启动路径通常被称为Composition Root。
在Composition Root中,Composer的工作是创建应用程序组件,管理它们的生存期,并在不再需要它们时处理它们。DI容器(如.NET Core DI容器)在您的系统中充当Composer,但您也可以手动完成这一操作——这种做法通常被称为Pure DI。
另请参阅这个答案,它也谈到了在SOLID原则的背景下进行处置。