实体框架从6.1.x升级到6.2.0会中断某些查询,除非我启用MARS [英] Entity Framework upgrade to 6.2.0 from 6.1.x breaks certain queries unless I enable MARS

查看:82
本文介绍了实体框架从6.1.x升级到6.2.0会中断某些查询,除非我启用MARS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近在一个大型项目中将EF 6.1.3升级到6.2.0,它破坏了我们大量的LINQ查询.启用MultipleActiveResultSets会使一切再次正常运行,但是我一直在努力了解所做的更改.我们已经使用EF多年了,并且经历了多个主要版本更改,没有任何问题.如果我简单地恢复到6.1.3,一切都会按预期再次运行-实际上,即使我在6.1.3中明确禁用了MARS,一切也都能正常运行.

I recently upgraded EF 6.1.3 to 6.2.0 on one of our large projects, and it has broken a significant amount of our LINQ queries. Enabling MultipleActiveResultSets causes everything to work as normal again, but I'm struggling to understand the change. We have been using EF for years and gone through multiple major version changes without any issue. If I simply revert back to 6.1.3, everything works again as expected - in fact everything works even if I explicitly disable MARS in 6.1.3.

让我给出一些简化的例子.第一个问题是嵌套查询:

Let me give a few simplified examples. The first problem is with nested queries:

foreach(var row in dbSet.Where(<condition>))
    foreach(var innerRow in otherDbSet.Where(_ => _.Property == row.Property))

在6.1.3中可以正常工作,但在6.2.0中会引发已经有一个打开的DataReader ..."异常.我了解异常的性质,可以通过在外部查询上调用ToList()首先将结果推送到内存中来解决此问题-我不明白,为什么我在6.1.3中不必这样做(即使禁用了MARS).简单地将整个外部集加载到内存中并不总是可取的.

This works fine in 6.1.3, but in 6.2.0 throws a "There is already an open DataReader..." exception. I understand the nature of the exception, and I can solve this by calling ToList() on the outer query to push the results into memory first - what I don't understand is why I didn't have to do this in 6.1.3 (even with MARS disabled). It isn't always desirable to simply load the whole outer set into memory.

这似乎也影响了延迟加载的属性.例如,我们从像这样的简单查询中构建ComboBoxes:

This also seems to impact lazy-loaded properties. For example, we build ComboBoxes from simple queries like this:

return db.Collection
    .Where(<condition>)
    .AsEnumerable()
    .Select(_ => new ListItem(_.Id, _.LazyNavigationProperty.Description))
    .ToList();

这在6.1.3中工作正常,但在6.2.0中再次引发已经有一个打开的DataReader ..."异常.解决方法是,我现在必须急于加载Navigation属性.

This works fine in 6.1.3, but again in 6.2.0 throws the "There is already an open DataReader..." exception. The fix is I now have to eager-load the navigation property.

最终我没有一个明确的问题,我只是想了解为什么小版本更新似乎导致查询处理方式发生重大突破.

Ultimately I don't have an explicit question, I'm just trying to understand why a minor version update seemingly caused major breaking changes in how queries are handled.

展望未来,这将影响太多的查询,我们无法进行重构.在研究问题时,我看到有关启用MARS的模糊警告,但没有人真正提出任何具体建议.是否有令人信服的理由不启用它?

Moving forward, this impacts far too many queries for us to refactor. When I was researching the problem, I saw vague warnings about enabling MARS, but nobody really gave anything concrete. Is there a compelling reason not to enable it?

推荐答案

之所以会出现此错误,是因为您在尝试打开另一个结果集时迭代了一个结果集(而第一个结果集还没有完成)->排序延迟加载(在您的情况下为第一个针对每个"迭代)->有许多方法可以解决此问题,就像您已经亲眼看到的一样:使用toList(首先放到内存中),因为不再使用数据读取器以打开集合.

you get this error because you're iterating through a result set while trying to open another result set (while the first one did not finish yet)-> sort of lazy loading (the first 'for each' iteration in your case) -> there are a lot of ways to solve this as you've already seen for yourself: using toList (drop to memory first), because it's no longer using the datareader to open the set.

它可能与6.2中的错误修复有关(发行说明: https://entityframework.net/ef-version-history )-看起来与以下内容相关:错误:重试查询或SQL命令失败,原因是另一个SqlParameterCollection已包含SqlParameter."

it looks like it MIGHT be related to a bug fix in 6.2 (release notes: https://entityframework.net/ef-version-history) - looks like related to: "Bug: Retrying queries or SQL commands fails with "The SqlParameter is already contained by another SqlParameterCollection.")

关于启用MARS: 您可以在此处找到特殊警告:

Regarding enabling MARS: you can find special warning here:

https ://docs.microsoft.com/zh-cn/dotnet/framework/data/adonet/sql/enabling-multiple-active-result-sets

这篇关于实体框架从6.1.x升级到6.2.0会中断某些查询,除非我启用MARS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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