AddDbContext 和 AddDbContextFactory 之间的区别

Difference between AddDbContext and AddDbContextFactory

实际上我是从 BlazorEF Core 开始的。在注册 DbContext 时,我卡住了。 DbContext 可以用 AddDbContextAddDbContextFactory 注册。但是有什么区别呢?

builder.Services.AddDbContext<DataContext>(opt => opt.UseSqlServer("..."));
builder.Services.AddDbContextFactory<DataContext>(opt => opt.UseSqlServer("..."));

从文档中我得到以下信息:

AddDbContext:

Use this method when using dependency injection ...

Entity Framework Core does not support multiple parallel operations being run on the same Microsoft.EntityFrameworkCore.DbContext instance. This includes both parallel execution of async queries and any explicit concurrent use from multiple threads.

AddDbContextFactory:

Registering a factory is recommended for Blazor applications and other situations where the dependency injection scope is not aligned with the context lifetime...

For convenience, this method also registers the context type itself as a scoped service. This allows a context instance to be resolved from a dependency injection scope directly or created by the factory, as appropriate.

那么我们是否可以全局地说,如果程序需要从不同线程访问 DbContext 或同时需要使用 AddDbContextFactory 注册上下文,因为当它被创建时(例如在控制器中)liftime 设置为 scoped,所以我们每次都会得到一个新的 DbContext?

private readonly DataContext _dbContext;

public BlogController(IDbContextFactory<DataContext> dbFactory)
{
  // Will be created as SCOPED DbContext?
  _dbContext = dbFactory.CreateDbContext();
}

我也发现了一个类似的问题AddDbContextAddDbContextFactory 内的生命周期是在注册期间设置的。或者我遗漏了什么。

所以我的问题一般是:

前提:我们希望 DbContext 的生命周期尽可能短。

对于 HTTP 服务器应用程序,我们有一个 Requets/Response 周期的范围。这是理想的,问题已解决:注入一个 Scoped DbContext。

对于 Blazor Server 应用程序,就像 WinForms 和 WPF 一样,我们没有如此方便的作用域。所以我们必须更直接地管理DbContext。

您可以使用具有 IDisposable and/or OwningComponentBase 的表单(页面)的生命周期,但该生命周期通常太长。

所以负担转移到了存储库(and/or 服务):他们必须在每个方法的基础上管理 DbContext。这就是 DbContextFactory 的用武之地:您可以简单地注入工厂,但每个方法看起来像:

void DoSomething()
{
   using (var ctx = _factory.CreateContext())
   {
     ...
   }
}

Blazor WebAssembly 应用程序不会直接使用 DbContext,因此以上内容主要适用于 Blazor Server。

When use AddDbContextFactory instead of AddDbContext?

在 Blazor 中始终使用 DbContextFactory。不过话说回来,肯定有人会想出一个例外!

What´s the lifetime difference from DbContext between DbContextFactory and AddDbContext?

DbContextFactory 管理它的 DBContext 的生命周期。应用“工作单元”原则,生命周期就是工作单元的生命周期。如果您将上下文直接添加到 DI 容器,例如使用 AddDbContext,那么它会在 DI 容器的生命周期内存在。

Should I generally use DbContextFactory for Blazor projects?

上面已经回答了

Is there a memory overhead when DbContext is created within a scoped lifetime?

当然可以。未处置的对象使用内存。作用域 DbContext 在 DI 容器的生命周期内存在。在容器本身被销毁之前,不会对容器内的对象调用 Dispose。这就是为什么您从不使用 Transient DbContexts 的原因。在会话 DI 容器被销毁之前,它们不会被释放。