升级到EntityFramework 6.1.3,现在正在接收上下文异常

本文关键字:异常 上下文 EntityFramework | 更新日期: 2023-09-27 18:24:06

我最近从实体框架5升级到实体框架6.1.3。

以下代码使用相同连接的多个上下文,以前在EF5:中运行良好

var Ids = MyDbContext.MyObject.Select(x => x.Id).Take(5).AsEnumerable();
var myObjects = MyDbContext2.MyObject.Where(x => Ids.Contains(x.Id)).ToList();

在EF6中,我收到:

指定的LINQ表达式包含对以下查询的引用与不同的上下文相关联。描述:未处理的在执行当前web请求期间发生异常。请查看堆栈跟踪以了解有关错误和它在代码中的来源。

异常详细信息:System.NotSupportedException:指定的LINQ表达式包含对与关联的查询的引用不同的语境。

实体框架中做了哪些更改以阻止此操作?我有没有办法在不更改代码的情况下让它工作?

升级到EntityFramework 6.1.3,现在正在接收上下文异常

将第一行从.AsEnumerable()更改为.ToList()

https://msdn.microsoft.com/en-us/data/hh949853.aspx#_Query_Plan_Caching

根据本文档,在EF 6中对Contains处理进行了更改,以优化生成底层SQL查询的方式。

只是在黑暗中拍摄而不看EF6的代码:

IEnumerable通常是一种延迟执行,在您以某种方式引用数据之前不会影响数据库。从框架的角度来看,这不是一个整数或长的列表,而是一个需要在不同上下文中执行的查询。由于它在不同的上下文中处于查询的中间,SQL解析器可能在使用新的处理方法解决它时遇到了问题。IEnumerable是Queryable和loaded之间的一种中途状态。我猜他们为优化所做的任何更改都不会再执行未完成的查询,而且如果引用的对象不是上下文的一部分,无论它是什么,它都会立即短路到异常

这也是为什么将其更改为List()可以使其工作的原因。您正在处理一个基元列表,而不是一个未解析的查询。

他们为什么要做出改变?我想他们有自己的原因(甚至超出了优化范围)。我可以想到的是,它可以防止查询生成部分修改IEnumerable的加载状态,以消除可能不需要的副作用。

您可以添加ToDictionary():

var Ids = (
  from x in MyDbContext.MyObject.Select()
  where x.Contains(x.Id)
  select x
).ToDictionary(x => x.Key).Keys.ToList();
var myObjects = (
  from y in MyDbContext2.MyObject
  where y => Ids.Contains(y.Id).ToList()
).ToList();
return myObjects;