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 派生对象,因为它也实现了IResettableServiceRelationalConnectionResetState()的默认实现是调用自己的Dispose()方法,而该方法又调用DbConnection.Dispose()

以上是关于AddDbContext 或 AddDbContextPool的主要内容,如果未能解决你的问题,请参考以下文章

在同一个项目中同时使用 AddDbContextFactory() 和 AddDbContext() 扩展方法

AddDbContext 是通过配置调用的,但是上下文类型“MyContext”只声明了一个无参数的构造函数?

AddDbContext was called with configuration, but the context type 'NewsContext' only declares

EFCore之增删改查

起订量和设置数据库上下文

identity使用mysql