我在我的asp.net Web应用程序中使用工作单元和存储库模式以及EF6。每次请求都会创建和销毁DbContext对象。
我认为在每个请求上创建新的dbcontext代价很高(我没有做任何性能基准测试)。
是否可以忽略在每个请求上创建DbContext的成本?有人做过一些台架标记吗?
答案 0 :(得分:5)
实体框架不是线程安全的,这意味着,您不能在多个线程中使用上下文。 IIS为发送到服务器的每个请求使用一个线程。鉴于此,您必须为每个请求设置一个上下文。否则,您会遇到无法解释和看似随机异常的主要风险,并且可能会将不正确的数据保存到数据库中。
最后,创建上下文的操作并不昂贵。如果您遇到缓慢的应用程序体验(不是在第一次启动时,而是在使用该站点之后),您的问题可能就在其他地方。
答案 1 :(得分:3)
创建一个新的上下文非常便宜,在我的应用程序中平均约为137个刻度(0.0000137秒)。
另一方面,挂在上下文上可能非常昂贵,所以经常处理它。您查询的对象越多,最终在上下文中跟踪的实体就越多。由于实体是POCOS,实体框架绝对无法知道您修改了哪些实体框架,除非在上下文中检查它们中的每一个并相应地进行标记。
当然,一旦它们被标记,它只会对需要更新的数据库进行数据库调用,但是当有大量实体被跟踪时,确定哪些需要更新是昂贵的,因为它必须根据已知值检查所有POCOS,看它们是否已经改变。
调用保存更改时的这种更改跟踪非常昂贵,如果您只是一次只读取和更新一条记录,那么最好在每条记录之后处理上下文并创建一条新记录。替代方法是挂在上下文中,这样您读取的每条记录都会在上下文中生成一个新实体,每次调用save更改时,它都会被一个实体变慢。
是的,它真的很慢。例如,如果您要更新10,000个实体,一次将一个实体加载到同一个上下文中,则第一次保存将只需要大约30个刻度,但是后续每个实验将花费更长时间到最后一个将超过30,000个刻度的点。相反,每次创建新上下文将导致每次更新一致的30个刻度。最后,由于挂起到上下文和所有被跟踪实体的累积减慢,在每次提交之前处理和重新创建上下文的时间最多只占20%(总时间的1/5)!
这就是为什么你应该只在上下文中调用保存更改一次,然后处理它。如果您在上下文中使用大量实体多次调用保存更改,则可能无法正确使用它。显然,特殊情况是当你做一些交易时。
如果需要执行某些事务操作,则需要手动打开自己的SqlConnection并在其上开始事务,或者需要在TransactionScope中打开它。然后,您可以通过传递相同的打开连接来创建DbContext。你可以反复这样做,每次处理DbContext对象,同时保持连接打开。通常,DbContext会为您处理打开和关闭上下文,但如果您将其传递给打开的连接,它将不会尝试自动关闭它。
这样,您可以将DbContext视为帮助跟踪打开的连接上的对象更改。您可以在同一连接上多次创建和销毁它,您可以在其中运行事务。了解幕后发生的事情非常重要。