AddDbContext或AddDbContextPool

89
在Asp.net Core应用程序中,我们应该使用哪一个?是“AddDbContext”还是“AddDbContextPool”?根据EF Core文档,“AddDbContextPool”提供了高性能,但默认的Asp.net Core项目模板使用“AddDbContext”。请注意,这里不要改变原始意思,只需确认译文是否准确无误即可。

12
除非您需要高性能,否则不需要使用AddDbContextPool。高性能意味着每秒(在您运行应用程序的机器上)2000-5000个请求。100个请求/分钟不是高性能,使用默认设置即可。 - Tseng
1
@Tseng,实际上怎么样?- @Gabriel的回答提到需要为并行查询创建新的DbContext - 使用AddDbContextPool是否会更简单,因为它可以自动完成这个过程?有什么缺点吗? - Jeppe
@Jeppe 我有点晚了,但连接池对于并行查询没有任何帮助。无论您是否使用连接池,从依赖注入中仍然只提供一个作用域的 DbContext - Gabriel Luci
1个回答

132
答案在这里(在“DbContext池”下面):https://learn.microsoft.com/zh-cn/ef/core/what-is-new/ef-core-2.0#dbcontext-pooling DbContext 不是线程安全的。因此,您不能同时为多个查询重用相同的 DbContext 对象(会出现奇怪的问题)。通常的解决方案是每次需要时创建一个新的 DbContext 对象,这就是 AddDbContext 的作用。
然而,重复使用 DbContext 对象并不会有什么问题,只要先前的查询已经完成即可。这就是 AddDbContextPool 的作用。它保持多个 DbContext 对象处于活动状态,并提供一个未使用过的对象,而不是每次都创建一个新的对象。
您可以自由选择使用哪个方法,两者都可以正常工作。使用池化方式具有一些性能上的优势。但是文档警告说,如果您的 DbContext 类中存在任何不应该在查询之间共享的私有属性,则不应该使用它。不过我想这种情况可能很少见,所以在大多数情况下,池化应该是适当的。

4
SQL事务怎么处理?如果事务的范围是每个连接,那么在连接池中会受到影响吗? - Alexsandro
1
默认的事务行为是每次调用 SaveChanges() 都会创建一个事务并自动关闭它。因此,只有在手动创建事务并未关闭时才可能出现问题。 - Gabriel Luci
5
当DbContext被放入连接池时,它是否会保持其底层连接的活动状态?我在文档中找不到任何线索。 - René Schindhelm
1
如果您正在处理该属性的重置,那么只要在需要时正确地重置它,您就不会有问题。 - Gabriel Luci
13
内部机制:当一个 DbContext 被返回到上下文池时,通过调用其 IResettableService.ResetState() 方法来重置上下文的状态。这个方法又调用了 GetResettableServices() 方法,然后也在返回的对象上调用了 IResettableService.ResetState() 方法。其中之一就是 EF Core 提供程序的派生对象 RelationalConnection,因为它同样实现了 IResettableService 接口。RelationalConnectionResetState() 的默认实现是调用自己的 Dispose() 方法,该方法再调用 DbConnection.Dispose() - lauxjpn
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接