C# Linq EF 多数据库查询报错 指定的 LINQ 表达式包含对与不同上下文关联的查询的引用。

在使用Linq 读EF进行两个数据库查询时出现如下错误

指定的 LINQ 表达式包含对与不同上下文关联的查询的引用。
C# Linq EF 多数据库查询报错 指定的 LINQ 表达式包含对与不同上下文关联的查询的引用。_第1张图片

解决方法

在对应查询加上 .AsEnumerable() 即可

具体如下图

//两个EF实例
EF1 db1 = new EF1();
EF2 db2 = new EF2();

//报错
var query = (from A in db1.Table
        	join B in db2.Table
            on A.ID equals B.ID
            select new
            {
               A.ID,
               A.NAME
             }).ToList();
//不报错 OK
var query2 = (from A in db1.Table.AsEnumerable()
              join B in db2.Table.AsEnumerable()
              on A.ID equals B.ID
              select new
              {
                  A.ID,
                  A.NAME
              }).ToList();

1、Iqueryable是Inherit IEnumerable的,所以AsEnumerable只是做的返回类型的转换。 此时并不会本地化。

2、但是IEnumerable数据在另外一个Iqueryable表达式树解析的时候,会本地化。

下面是引用文章:https://www.cnblogs.com/cqj98k/p/10092067.html

Linq中 AsQueryable(), AsEnumerable()和ToList()的区别和用法:

在写LINQ语句的时候,往往会看到AsEnumerable() ,AsQueryable()
和ToList()的用法,三者有何区别呢?以下是我的理解,有毛病请大家指教! 在System.Linq命名空间下,有两个静态类:
Enumerable类,它针对继承了IEnumerable接口的集合进行扩展;
Queryable类,针对继承了IQueryable接口的集合进行扩展。 一、AsQueryable(): 先说说什么是
IQueryable,AsQueryable将一个序列向下转换为一个IQueryable, 它生成了一个本地查询的IQueryable包装。
1,lazy load 特性 以下是一段最常见的代码: var products = db.Product.where(p =>
p.Type == “food”).select(p => new { p.Id, p.Name, p.CreateTime});
注意:Select() 的返回类型为 IQueryable,为 IQueryable, 语句执行后不会立刻查询数据库, 而是在迭代使用
products 时才会查数据库, 具有 lazy load 的特性, 按需查数据库可提高程序效率。

2,高程序效率. 迭代时上面的代码类似于下面的 sql 语句: select Id, Name, CreateTime from
Product where Type = ‘food’ 对 products 再次使用数据库查询操作, 运行时会把结果合并为1条 sql
语句, 如下, var products = db.Product.where(p => p.Type ==
“food”).select(p => new { p.Id, p.Name, p.CreateTime}); var
orderedProducts = products.OrderBy(p => p.CreateTime); 迭代时生成的 sql
语句类似: select Id, Name, CreateTime from Product where Type = ‘food’
order by CreateTime IQueryable 有诸多限制, 只支持数据库查询语法, 无法支持 Linq to object
的操作, 是LINQ TO SQL。 结论:AsQueryable将一个序列向下转换为一个IQueryable,
它生成了一个本地查询的IQueryable包装。 二、AsEnumerable() 同样支持 lazy
load,是延迟执行的,实际上什么都没有发生,当真正使用对象的时候(例如调用:First, Single,
ToList…的时候)才执行。 但不要滥用。迭代时遇到 AsEnumerable() 会先进行 sql 查询, 但是,
千万不要为了方便而滥用 AsEnumerable(), 可能会严重消耗资源,能进行 Linq to object 操作。

eg:var products = db.Product.AsEnumerable().Select(p => new {p.Id,
p.Name, p.CreateTime.Date});
对IQueryable对象使用AsEnumerable()后,仍然是延迟执行,不过此时对象本质已经变了。
上面的代码在查询时会把整个Product表的结果存放进内存, 然后进行 .Select 查询,严重消耗资源。
结论:AsEnumerable将一个序列向上转换为一个IEnumerable,
强制将Enumerable类下面的查询操作符绑定到后续的子查询当中。
AsEnumerable()延迟执行,不会立即执行。当你调用.AsEnumerable()的时候,实际上什么都没有发生。
注意:IQueryable实现了IEnumberable接口。但IEnumerable 换成IQueryable后速度提高很多。
IQueryable接口与IEnumberable接口的区别: IEnumerable 泛型类在调用自己的SKip 和 Take
等扩展方法之前数据就已经加载在本地内存里了,而IQueryable 是将Skip ,take
这些方法表达式翻译成T-SQL语句之后再向SQL服务器发送命令,它并不是把所有数据都加载到内存里来才进行条件过滤。 三、ToList()
调用 ToList() 会立刻查询并保存结果, 而不会等到迭代时才查询,作用和 lazy load 是相反的。 在需要得到完整结果后,
再处理的场景, 需要使用 ToList()。

你可能感兴趣的:(C#)