DbContext & ef-core 中的 DbcontextPool

发布于 2025-01-20 19:15:04 字数 1337 浏览 0 评论 0原文

我阅读了许多有关EFCORE及其一生中DBContext的文档和文章,但是,我有一些问题。

基于此链接“ https:https:/ microsoft.com/en-us/ef/core/dbcontext-configuration /“ dbcontext的最佳寿命和adddbContext的默认寿命为 scope 该文档上的句子。

dbContext不是线程安全。 线程。在继续使用之前,请确保等待所有异步电话 上下文实例。”

另一方面,也提到了

dbContext是 可免于并发访问在大多数问题中 ASP.NET核心应用程序因为只有一个线程执行 每个客户的请求在给定时间,并且因为每个请求获取 单独的依赖注入范围(因此 dbContext实例)。”

  1. dbContext

实例 但是,Singleton dbContext ,但是, adddbContextpool可以注册Singleton dbcontext 。 因此,关于DBContextpool有一些问题。

  1. 使用DBContextPool而不是DBContext有什么影响?
  2. 什么时候应该使用它,当我们使用上下文池时应该考虑什么?
  3. dbcontextpool是线程安全吗?
  4. 由于在整个应用程序的一生中都存储了许多DBSET实例,因此是否有内存问题?
  5. 变更跟踪或EF的任何部分在DB上下文库中是否会失败还是不会失败?

每个dbcontext每个网络请求...为什么?

://stackoverflow.com/questions/3266295/net-entity-framework-and-transactions/3266481#3266481“> .net Entity Entity框架和交易

I read a lot of documents and articles about DBcontext in Efcore and its lifetime, however, I have some questions.

Based on this link "https://learn.microsoft.com/en-us/ef/core/dbcontext-configuration/" the best lifetime of DBcontext and default lifetime of AddDbContext is scope, but there is a contradiction in the two below sentences on this document.

"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."

on the other hand, it was mentioned too,

"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. I was confused about whether registering DBcontext as a scoped service is thread-safe or not?
  2. What are the problems of registering DBcontext as a singleton service in detail?

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.

  1. what are the impacts of using the DbContextPool instead of the DbContext?
  2. when we should use it and what should be considered when we use contextPool?
  3. DbContextPool is thread-safe?
  4. Has it memory issues because of storing a number of dbset instances throughout the application's lifetime?
  5. change-tracking or any parts of the ef would be failed or not in the DB context pool?

One DbContext per web request... why?

.NET Entity Framework and transactions

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

月野兔 2025-01-27 19:15:04

我理解为什么您认为 Microsoft 文档中的语言令人困惑。我将为您解释一下:

  • “DbContext 不是线程安全的。”此语句意味着从多个线程并行访问 DbContext 是不安全的。堆栈溢出答案您已经引用过,解释一下。
  • “不要在线程之间共享上下文。”这种说法很令人困惑,因为异步(async/await)操作倾向于跨多个线程运行,尽管从来不是并行的。更简单的说法是:“不要在 Web 请求之间共享上下文”,因为单个 Web 请求通常运行单个工作单元,尽管它可能会异步运行其代码,但它通常不会运行它的代码是并行的。另一种说法是“不要并行访问单个 DbContext 实例”,如果在(Web)请求之间共享单个 DbContext 就会发生这种情况。
  • “Dbcontext 在大多数 ASP.NET Core 应用程序中不会出现并发访问问题”:此文本具有误导性,因为它可能会让读者相信 DbContext 实例是线程安全的,但事实并非如此。作者在这里想说的是,使用默认配置(即使用 AddDbContext()),ASP.NET Core 确保每个请求都有自己的 DbContext因此,默认情况下它“不会受到并发访问的影响”。

1 我很困惑将 DBcontext 注册为作用域服务是否是线程安全的?

DbContext 实例本身不是线程安全的,这就是为什么您应该将它们注册为作用域,因为这会阻止它们被从多个请求,因此是并行的。

这不会阻止您在单个请求中旋转(后台)操作,所有操作都并行访问 DbContext 实例。当您使用 Parallel.ForEach 或忘记等待异步操作(导致其在后台并行运行)时,可能会发生这种情况。应避免出现此类情况,因为 DbContext 不是线程安全的。

2 将DBcontext注册为单例服务具体有哪些问题?

您已引用的此答案中已对此进行了详细描述。我认为这个答案涉及很多细节,我不会在这里重复。

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

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

  • 池机制确保并行请求获得自己的 DbContext 实例。
  • 因此,池化时存在多个 DbContext 实例,而使用 Singleton 生活方式时,整个应用程序仅存在一个实例。
  • 因此,使用单例生活方式可以确保重复使用一个实例,这会导致(再次)出现无数问题 此处
  • 池机制确保当 DI 作用域结束时,DbContext 被“清理”并带回池中,以便新请求可以重用它。

使用 DbContextPool 而不是 DbContext 有什么影响?

有关此内容的更多信息,请参见 文档。

什么时候应该使用它,使用contextPool时应该考虑什么?

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

DbContextPool 是线程安全的吗?

是的,就像将 DbContext 注册为 Scoped 一样,是线程安全的;如果您不小心保留了跨请求重用的对象内的 DbContext 实例,则此保证将被破坏。您必须妥善保管 Scoped 对象,以防止它们成为 强制依赖项

是否会因为在应用程序的整个生命周期中存储大量数据库集实例而出现内存问题?

记忆损失几乎不会被注意到。对于请求结束后带回池中的每个 DbContext,所谓的一级缓存都会被清除。这是为了防止 DbContext 变得过时并防止内存问题。

更改跟踪或 ef 的任何部分将失败或不在数据库上下文池中?

不,事实并非如此。在大多数情况下,使您的 DbContext 池化只需要进行基础架构更改(更改应用程序的启动路径),并且在很大程度上对应用程序的其余部分是透明的。但再次强调,请务必阅读 可以让您熟悉使用DbContext池的后果。

I understand why you think the language in the Microsoft documents is confusing. I'll unravel it for you:

  • "DbContext is not thread-safe." This statement means that it's not safe to access a DbContext from multiple threads in parallel. The stack overflow answers you already referenced, explain this.
  • "Do not share contexts between threads." This statement is confusing, because asynchronous (async/await) operations have the tendency to run across multiple threads, although never in parallel. A simpler statement would be: "do not share contexts between web requests," because a single web request typically runs a single unit of work and although it might run its code asynchronously, it typically doesn't run its code in parallel. Another way of putting it is "do not access a single DbContext instance in parallel," which is what will happen if a single DbContext is shared between (web) requests.
  • "Dbcontext is safe from concurrent access issues in most ASP.NET Core applications": This text is misleading, because it might make the reader believe that DbContext instances are thread-safe, which they aren't. What the writers mean to say here is that, with the default configuration (i.e. using AddDbContext<T>(), ASP.NET Core ensures that each request gets its own DbContext instance, making it, therefore, "safe from concurrent access" by default.

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

DbContext instances are by themselves not thread-safe, which is why you should register them as Scoped, because that would prevent them from being accessed from multiple requests, and thus in parallel.

This doesn't prevent you from spinning of (background) operations from within a single request all accessing the DbContext instance in parallel. This could happen when you use Parallel.ForEach or when you forget to await an asynchronous operation (causing it to run in parallel in the background). These types of situations should be prevented because, again, DbContext is not thread-safe.

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

This is already described in detail in this answer, which you already referenced. I think that answer goes into a lot of detail, which I won't repeat here.

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.

The DbContext pooling feature is very different from registering DbContext as singleton, because:

  • The pooling mechanism ensures that parallel requests get their own DbContext instance.
  • Therefore, multiple DbContext instances exist with pooling, while only a single instance for the whole application exists when using the Singleton lifestyle.
  • Using the singleton lifestyle, therefore, ensures that one single instance is reused, which causes the myriad of problems laid out (again) here.
  • The pooling mechanism ensures that, when a DI scope ends, the DbContext is 'cleaned' and brought back to the pool, so it can be reused by a new request.

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

More information about this is given in this document.

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

When your application requires the performance benefits that it brings. This is something you might want to benchmark before deciding to add it.

DbContextPool is thread-safe?

Yes, in the same way as registering a DbContext as Scoped is thread-safe; in case you accidentally hold on to a DbContext instance inside an object that is reused across requests, this guarantee is broken. You have to take good care of Scoped objects to prevent them from becoming Captive Dependencies.

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

The memory penalty will hardly ever be noticeable. The so-called first-level cache is cleared for every DbContext that is brought back to the pool after a request ends. This is to prevent the DbContext from becoming stale and to prevent memory issues.

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

No, it doesn't. For the most part, making your DbContext pooled is something that only requires infrastructural changes (changes to the application's startup path) and is for the most part transparent to the rest of your application. But again, make sure to read this to familiar yourself with the consequences of using DbContext pooling.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文