我们真的需要在Repository或UnitOfWork类中实现IDisposable吗



首先,让我们看看微软对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原则的背景下进行处置。

最新更新