AddDbContext 或 AddDbContextPool
Posted
技术标签:
【中文标题】AddDbContext 或 AddDbContextPool【英文标题】:AddDbContext or AddDbContextPool 【发布时间】:2018-07-04 17:50:00 【问题描述】:对于 Asp.net Core 应用程序,我们必须使用哪一个? AddDbContext
还是 AddDbContextPool
?根据 EF Core 文档,AddDbContextPool
提供高性能,但默认的 Asp.net Core 项目模板使用AddDbContext
。
【问题讨论】:
除非您需要高性能,否则您不需要AddDbContextPool
。高性能意味着每秒 2000-5000 个请求(每台运行应用程序的机器)。 100 次请求/分钟并不是高性能,您可以使用默认值
@Tseng 实际情况如何? - @Gabriel 的回答提到必须为并行查询创建新的 DbContext
- AddDbContextPool
会更简单,因为它会自动执行此操作吗?有什么缺点吗?
@Jeppe 我有点晚了,但是池对并行查询完全没有帮助。无论您是否使用池化,依赖注入的每个作用域仍然只为您提供一个 DbContext
。
【参考方案1】:
答案在这里(在“DbContext pooling”下):https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-2.0#dbcontext-pooling
DbContext
不是线程安全的。所以你不能同时为多个查询重用相同的DbContext
对象(奇怪的事情发生了)。通常的解决方案是在每次需要时创建一个新的DbContext
对象。这就是AddDbContext
所做的。
但是,在先前的查询已经完成后重用 DbContext
对象并没有错。这就是AddDbContextPool
所做的。它使多个DbContext
对象保持活动状态,并为您提供一个未使用的对象,而不是每次都创建一个新对象。
您使用哪一个取决于您。两者都会起作用。池化有一些性能提升。但是文档警告说,如果您在 DbContext
类中使用不应在查询之间共享的任何私有属性,则不应使用它。不过我想这非常罕见,因此在大多数情况下,池化应该是合适的。
【讨论】:
但是,sql 事务呢?如果transations范围是每个连接,连接池中是否会受到影响? default transaction behavior 是它为每次调用SaveChanges()
创建一个事务并自动关闭它。因此,如果您手动创建事务并且不将其关闭,这可能会成为问题。
返回的 DbContext 是否会在池化时保持其底层连接处于活动状态?我似乎在文档中找不到任何线索。
@djsoteric 如果您正在处理该属性的重置,那么是的,只要您在需要时正确重置它就可以了。
内部:当 DbContext
返回到上下文池时,上下文的状态正在通过调用其 IResettableService.ResetState()
方法进行重置。该方法依次调用GetResettableServices()
方法,然后也对返回的对象调用IResettableService.ResetState()
。这些对象之一是 EF Core 提供程序RelationalConnection
派生对象,因为它也实现了IResettableService
。 RelationalConnection
中ResetState()
的默认实现是调用自己的Dispose()
方法,而该方法又调用DbConnection.Dispose()
。以上是关于AddDbContext 或 AddDbContextPool的主要内容,如果未能解决你的问题,请参考以下文章
在同一个项目中同时使用 AddDbContextFactory() 和 AddDbContext() 扩展方法
AddDbContext 是通过配置调用的,但是上下文类型“MyContext”只声明了一个无参数的构造函数?
AddDbContext was called with configuration, but the context type 'NewsContext' only declares