DbContext & ef-core 中的 DbcontextPool
我阅读了许多有关EFCORE及其一生中DBContext的文档和文章,但是,我有一些问题。
基于此链接“ https:https:/ microsoft.com/en-us/ef/core/dbcontext-configuration /“ dbcontext的最佳寿命和adddbContext的默认寿命为 scope 该文档上的句子。
“ dbContext不是线程安全。 线程。在继续使用之前,请确保等待所有异步电话 上下文实例。”
另一方面,也提到了
“ dbContext是 可免于并发访问在大多数问题中 ASP.NET核心应用程序因为只有一个线程执行 每个客户的请求在给定时间,并且因为每个请求获取 单独的依赖注入范围(因此 dbContext实例)。”
- dbContext
- 。
实例 但是,Singleton dbContext ,但是, adddbContextpool可以注册Singleton dbcontext 。 因此,关于DBContextpool有一些问题。
- 使用DBContextPool而不是DBContext有什么影响?
- 什么时候应该使用它,当我们使用上下文池时应该考虑什么?
- dbcontextpool是线程安全吗?
- 由于在整个应用程序的一生中都存储了许多DBSET实例,因此是否有内存问题?
- 变更跟踪或EF的任何部分在DB上下文库中是否会失败还是不会失败?
每个dbcontext每个网络请求...为什么?
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)."
- I was confused about whether registering DBcontext as a scoped service is thread-safe or not?
- 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.
- what are the impacts of using the DbContextPool instead of the DbContext?
- when we should use it and what should be considered when we use contextPool?
- DbContextPool is thread-safe?
- Has it memory issues because of storing a number of dbset instances throughout the application's lifetime?
- change-tracking or any parts of the ef would be failed or not in the DB context pool?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我理解为什么您认为 Microsoft 文档中的语言令人困惑。我将为您解释一下:
DbContext
是不安全的。堆栈溢出答案您已经引用过,解释一下。DbContext
就会发生这种情况。DbContext
实例是线程安全的,但事实并非如此。作者在这里想说的是,使用默认配置(即使用AddDbContext()
),ASP.NET Core 确保每个请求都有自己的DbContext
因此,默认情况下它“不会受到并发访问的影响”。DbContext 实例本身不是线程安全的,这就是为什么您应该将它们注册为
作用域
,因为这会阻止它们被从多个请求,因此是并行的。这不会阻止您在单个请求中旋转(后台)操作,所有操作都并行访问
DbContext
实例。当您使用 Parallel.ForEach 或忘记等待异步操作(导致其在后台并行运行)时,可能会发生这种情况。应避免出现此类情况,因为DbContext
不是线程安全的。您已引用的此答案中已对此进行了详细描述。我认为这个答案涉及很多细节,我不会在这里重复。
DbContext
池功能与将DbContext
注册为单例有很大不同,因为:DbContext
实例。DbContext
被“清理”并带回池中,以便新请求可以重用它。有关此内容的更多信息,请参见 此文档。
当您的应用程序需要它带来的性能优势时。在决定添加之前,您可能需要对其进行基准测试。
是的,就像将
DbContext
注册为Scoped
一样,是线程安全的;如果您不小心保留了跨请求重用的对象内的DbContext
实例,则此保证将被破坏。您必须妥善保管Scoped
对象,以防止它们成为 强制依赖项。记忆损失几乎不会被注意到。对于请求结束后带回池中的每个
DbContext
,所谓的一级缓存都会被清除。这是为了防止 DbContext 变得过时并防止内存问题。不,事实并非如此。在大多数情况下,使您的
DbContext
池化只需要进行基础架构更改(更改应用程序的启动路径),并且在很大程度上对应用程序的其余部分是透明的。但再次强调,请务必阅读 此可以让您熟悉使用DbContext
池的后果。I understand why you think the language in the Microsoft documents is confusing. I'll unravel it for you:
DbContext
from multiple threads in parallel. The stack overflow answers you already referenced, explain this.DbContext
is shared between (web) requests.DbContext
instances are thread-safe, which they aren't. What the writers mean to say here is that, with the default configuration (i.e. usingAddDbContext<T>()
, ASP.NET Core ensures that each request gets its ownDbContext
instance, making it, therefore, "safe from concurrent access" by default.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 useParallel.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.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.
The
DbContext
pooling feature is very different from registeringDbContext
as singleton, because:DbContext
instance.DbContext
instances exist with pooling, while only a single instance for the whole application exists when using the Singleton lifestyle.DbContext
is 'cleaned' and brought back to the pool, so it can be reused by a new request.More information about this is given in this document.
When your application requires the performance benefits that it brings. This is something you might want to benchmark before deciding to add it.
Yes, in the same way as registering a
DbContext
asScoped
is thread-safe; in case you accidentally hold on to aDbContext
instance inside an object that is reused across requests, this guarantee is broken. You have to take good care ofScoped
objects to prevent them from becoming Captive Dependencies.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 theDbContext
from becoming stale and to prevent memory issues.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 usingDbContext
pooling.