在ASP.Net上每个Web请求创建dbcontext的成本 [英] Cost of creating dbcontext per web request on ASP.Net

查看:77
本文介绍了在ASP.Net上每个Web请求创建dbcontext的成本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在asp.net Web应用程序中使用工作单元和存储库模式以及EF6.在每个请求上都会创建并销毁DbContext对象.

我认为在每个请求上创建新的dbcontext成本很高(我没有做任何性能基准测试).

在每个请求上创建DbContext的开销可以忽略吗?有人做过基准测试吗?

解决方案

创建新上下文非常便宜,在我的应用程序中,平均大约需要137滴答声(0.0000137秒).

另一方面,挂在上下文上可能会非常昂贵,因此请经常进行处理.

查询的对象越多,最终在上下文中跟踪的实体越多.由于实体是POCOS,因此实体框架绝对无法知道您已修改了哪些实体,只能检查上下文中的每个实体并相应地对其进行标记.

当然,一旦标记了它们,它只会对需要更新的对象进行数据库调用,但是确定哪些对象需要更新,当要跟踪的实体很多时,这很昂贵,因为它必须对照已知值检查所有POCOS,以查看它们是否已更改.

在调用保存更改时,这种更改跟踪非常昂贵,以至于如果您一次只读取和更新一条记录,那么最好在每条记录之后丢弃上下文并创建一个新记录.另一种方法是挂在上下文上,这样,您读取的每条记录都会在上下文中产生一个新实体,并且每次调用保存更改时,它会变慢一个实体.

是的,它确实速度较慢.例如,如果要更新10,000个实体,一次将一个实体加载到同一上下文中,则第一次保存将只花费大约30个滴答声,但是随后的每个保存将花费更长的时间,最后一个保存将花费30,000个滴答声.相反,每次创建一个新的上下文将导致每次更新一致的30个滴答声.最后,由于挂在上下文和所有跟踪的实体上的累积速度变慢,因此在每次提交之前处理和重新创建上下文仅花费20%的时间(总时间的1/5)! >

这就是为什么您实际上应该只在上下文中调用一次保存更改,然后再进行处理.如果您多次调用保存更改并在上下文中使用许多实体,则可能未正确使用它.显然,例外情况是在您进行事务性操作时.

如果需要执行某些事务操作,则需要手动打开自己的SqlConnection并在其上开始事务,或者需要在TransactionScope中打开它.然后,您可以通过传递相同的打开连接来创建DbContext.您可以一遍又一遍地执行此操作,每次保持连接打开时都处理DbContext对象.通常,DbContext会为您处理打开和关闭上下文,但是如果您将其传递为打开连接,它将不会尝试自动关闭它.

这样,您将DbContext视为仅用于跟踪打开的连接上的对象更改的帮助程序.您可以在同一连接上创建和销毁它多次,并可以在其中运行事务.了解引擎盖下发生的事情非常重要.

I am using Unit of work and Repository pattern along with EF6 in my asp.net web application. DbContext object is getting created and destroyed on every request.

I am thinking that it is costly creating the new dbcontext on every request(I have not done any performance bench marking).

Is this cost of creating DbContext on every request can be ignored ? Does anybody done some bench marking?

解决方案

Creating a new context is ridiculously cheap, on the order of about 137 ticks on average (0.0000137 seconds) in my application.

Hanging onto a context, on the other hand, can be incredibly expensive, so dispose of it often.

The more objects you query, the more entities end up being tracked in the context. Since entities are POCOS, entity framework has absolutely no way of knowing which ones you've modified except to examine every single one of them in the context and mark it accordingly.

Sure, once they're marked, it will only make database calls for the ones that need updated, but it's determining which ones need updated that is expensive when there are lots of entities being tracked, because it has to check all the POCOS against known values to see if they've changed.

This change tracking when calling save changes is so expensive, that if you're just reading and updating one record at a time, you're better off disposing of the context after each record and creating a new one. The alternative is hanging onto the context, such that every record you read results in a new entity in the context, and every time you call save changes it's slower by one entity.

And yes, it really is slower. If you're updating 10,000 entities for example, loading one at a time into the same context, the first save will only take about 30 ticks, but every subsequent one will take longer to the point where the last one will take over 30,000 ticks. In contrast, creating a new context each time will result in a consistent 30 ticks per update. In the end, because of the cumulative slow-down of hanging onto the context and all the tracked entities, disposing of and recreating the context before each commit ends up taking only 20% as long (1/5 the total time)!

That's why you should really only call save changes once on a context, ever, then dispose of it. If you're calling save changes more than once with a lot of entities in the context, you may not be using it correctly. The exceptional case, obviously, is when you're doing something transactional.

If you need to perform some transactional operation, then you need to manually open your own SqlConnection and either begin a transaction on it, or you need to open it within a TransactionScope. Then, you can create your DbContext by passing it that same open connection. You can do that over and over, disposing of the DbContext object each time while leaving the connection open. Usually, DbContext handles opening and closing the context for you, but if you pass it an open connection, it won't try to close it automatically.

That way, you treat the DbContext as just a helper for tracking object changes on an open connection. You create and destroy it as many times as you like on the same connection, where you can run your transaction. It's very important to understand what's going on under the hood.

这篇关于在ASP.Net上每个Web请求创建dbcontext的成本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆