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

Fra*_*hes 3 c# dependency-injection unit-of-work asp.net-core

首先,让我们看看微软对Asp.Net Core的默认依赖注入服务的看法:

该框架负责创建依赖项实例,并在不再需要它时将其处置。

https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1#disposal-of-services

即框架将调用类Dispose方法(假设该类实现IDisposable)

其次,DbContext类确实确实实现了IDisposable。

第三,在我们的Startup.cs类中,我们通过AddDbContext方法添加DbContext,默认情况下,该方法将作为Scoped实例添加(即,我们的DbContext被创建并在每个单个请求上进行垃圾回收)。

每个请求一次创建范围的生命周期服务。

https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1#service-lifetimes

例如

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddDbContext<TheStoreDbContext>(ConfigureDbContext)      
        .AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2) 
}
Run Code Online (Sandbox Code Playgroud)

结论,我们不需要在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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

你怎么看?这是一个有效的问题吗?不在任何地方显式调用Dispose()方法是否有意义?

Ste*_*ven 7

您在UnitOfWork课堂上的例子实际上是一种不好的做法。规则是,一个类只能处置它所拥有的东西。在的情况下UnitOfWork,但是,它并没有自己DbContext作为不被创建UnitOfWork,而是由其他人提供。

进行UnitOfWork处置DbContext甚至是有问题的,因为UnitOfWork在处置时无法知道DbContext系统中的其他类是否仍在使用该方法UnitOfWork。换句话说,系统在UnitOfWork开始处理该依赖项时可能会崩溃。

因此,如果您遵循只处理自己拥有的东西的规则,则意味着UnitOfWork实际上根本不应该实现IDisposable。这意味着您让“其他人”控制的生命周期DbContext

将对依赖项生存期的控制(如DbContext)移交给第三方的想法并不是什么新鲜事物,当然也不是特定于新Microsoft DI容器的事物。实际上,这是一个古老的想法,即您在应用程序的启动路径中集中控制应用程序组件的生命周期。在DI的上下文中,此启动路径通常称为“ 合成根”

在“合成根目录”内部,Composer的工作是创建应用程序组件,管理它们的生命周期并在不再需要它们时进行处理。DI容器(如.NET Core DI容器)在您的系统中充当Composer,但您也可以手动完成此操作-这种做法通常称为Pure DI