Entity Framework upgrade to 6.2.0 from 6.1.x breaks certain queries unless I enable MARS

杀马特。学长 韩版系。学妹 提交于 2020-01-22 13:26:31

问题


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))

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.

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();

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.

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?


回答1:


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.

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.")

Regarding enabling MARS: you can find special warning here:

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




回答2:


Entity Framework is supposed to deliver a tiny abstraction on your database model.

Such work requires performing multiple queries under the hood. The engine might also require more queries necessary when compared to the same workload encoded by hand.

This is a physiological evolution in order to be able to handle all possible user requests. Simply upgrading to a different Entity Framework version, can introduce differences on the database workload emitted under the hood.

MARS is required as EF changed the way object retrieval is performed (particularly, within loops combined with lazy loading). Unfortunately, most of the times, you are required to use MARS when using Entity Framework.

Nowadays, using async/await usually requires MARS too.

You can find additional information about how related entities are loaded on MSDN Loading Related Objects and Enabling Multiple Active Result Sets. This interesting blog goes a little more deeper.



来源:https://stackoverflow.com/questions/47208528/entity-framework-upgrade-to-6-2-0-from-6-1-x-breaks-certain-queries-unless-i-ena

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!