ef-core 中的 DbContext 和 DbcontextPool

DbContext & DbcontextPool in ef-core

我阅读了很多关于 Efcore 中的 DBcontext 及其生命周期的文档和文章,但是,我有一些疑问。

基于这个link "https://docs.microsoft.com/en-us/ef/core/dbcontext-configuration/" DBcontext的最佳生命周期和AddDbContext的默认生命周期是scope,但是有矛盾本文档中的以下两个句子。

"DbContext is not thread-safe. Do not share contexts between threads. Make sure to await all async calls before continuing to use the context instance."

另一方面,也提到了,

"Dbcontext is safe from concurrent access issues in most ASP.NET Core applications because there is only one thread executing each client request at a given time, and because each request gets a separate dependency injection scope (and therefore a separate DbContext instance)."

  1. 我对将 DBcontext 注册为作用域服务是否线程安全感到困惑?
  2. 详细的把DBcontext注册成单例服务有哪些问题?

此外,我阅读了一些禁止注册单例DbContext的文档,但是,AddDbContextPool 使得注册单例DBcontext。 所以有一些关于 Dbcontextpool 的问题。

  1. 使用 DbContextPool 而不是 DbContext 有什么影响?
  2. 什么时候使用contextPool需要注意什么?
  3. DbContextPool 是线程安全的吗?
  4. 它是否因为在应用程序的整个生命周期中存储大量 dbset 实例而出现内存问题?
  5. 更改跟踪或 ef 的任何部分在数据库上下文池中是否会失败?

One DbContext per web request... why?

.NET Entity Framework and transactions

我理解您为什么认为 Microsoft 文档中的语言令人困惑。我会为你解开它:

  • “DbContext 不是 thread-safe。”此语句意味着从多个线程 并行 访问 DbContext 是不安全的。您已经引用的堆栈溢出答案,对此进行解释。
  • “不要在线程之间共享上下文。”这种说法令人困惑,因为异步 (async/await) 操作倾向于 运行 跨多个线程,尽管从不并行。一个更简单的声明是:“不要在 Web 请求之间共享上下文”,因为单个 Web 请求通常 运行 是一个 工作单元 ,尽管它可能 运行 它的代码是异步的,它通常不会 运行 它的代码是并行的。
  • “在大多数 ASP.NET 核心应用程序中,Dbcontext 不会出现并发访问问题”:该文本有点误导,因为它可能使 reader 认为 DbContext 实例是 thread-safe,但他们不是。作者在这里想说的是,使用默认配置(即使用 AddDbContext<T>(),ASP.NET Core 确保每个请求都有自己的 DbContext 实例,因此,“安全来自并发访问”。

1 I was confused about whether registering DBcontext as a scoped service is thread-safe or not?

DbContext 实例本身不是 thread-safe,这就是为什么你应该将它们注册为Scoped ,因为这会阻止它们被多个请求访问,这将使它们的使用 thread-safe.

2 What are the problems of registering DBcontext as a singleton service in detail?

这已在您已引用的 this answer 中进行了详细描述。这个回答我觉得很详细,这里就不重复了。

In addition, I read some docs that prohibit registering singleton DbContext, however, AddDbContextPool makes to register singleton DBcontext. so there are some questions about the Dbcontextpool.

DbContext 池功能与将 DbContext 注册为单例有很大不同,因为:

  • 池机制确保并行请求获得自己的 DbContext 实例。
  • 因此,多个 DbContext 实例存在池化,而当使用 Singleton 生活方式时,整个应用程序只存在一个实例。
  • 因此,使用单例生活方式可确保重复使用一个实例,这会导致(再次)列出的无数问题here
  • 池机制确保当 DI 范围结束时,DbContext 'cleaned' 并返回到池中,因此它可以被新请求重用。

what are the impacts of using the DbContextPool instead of the DbContext?

this 文档中提供了更多相关信息。

when we should use it and what should be considered when we use contextPool?

当您的应用程序需要它带来的性能优势时。这是您在决定添加之前可能需要进行基准测试的东西。

DbContextPool is thread-safe?

是的,就像注册一个DbContext一样Scoped是thread-safe;如果您不小心在跨请求重用的对象中持有 DbContext 实例,则此保证将被打破。您必须妥善保管 Scoped 个对象,以防止它们变成 Captive Dependencies.

Has it memory issues because of storing a number of dbset instances throughout the application's lifetime?

内存损失几乎不会被注意到。 so-called first-level 缓存会为请求结束后带回池中的每个 DbContext 清除。这是为了防止 DbContext 变得陈旧并防止内存问题。

change-tracking or any parts of the ef would be failed or not in the DB context pool?

不,不是。在大多数情况下,使 DbContext 池化只需要更改基础结构(更改应用程序的启动路径)并且在很大程度上对应用程序的其余部分是透明的。但同样,请务必阅读 this 以熟悉使用 DbContext 池的后果。