LINQ.Contains超过2100记录报异常Exception的问题

今天遇到一个LINQ的异常: 传入的表格格式数据流(TDS)远程过程调用(RPC)协议流不正确。此 RPC 请求中提供了过多的参数。最多应为 2100。

代码是:

Table<MyEntity> tbl = dataContext.GetTable<MyEntity>();
tbl.
where(t => AnotherList.Contains(t.EntityID)).select(....)

报错的地方就是.Contains函数,当AnotherList的元素个数超过2100,LINQ的.Contains最大支持2100,超过就会报这个异常。这句LINQ背后的SQL语句可能是这样的:

SELECT [t0].....
FROM MyEntity AS [t0]
WHERE [t0].[EntityID] IN (@p0, @p1, @p2, @p3, @p4......2100)

所以就遇到SQL过长的问题,微软为了防止这个问题,就人为LINQ.Contains()限制了2100这个数量,很是奇怪。

解决办法很简单,只要将调用数据源的AsEnumerable()运算符就可以了。例如:

var tbl = dataContext.GetTable<MyEntity>().AsEnumerable();
tbl.
where(t => AnotherList.Contains(t.EntityID)).select(....)

其它方法也有,就是转变思路,用JOIN的方式,而不要用WHERE ... IN (...,...,...)的方式。


为什么.AsEnumerable()这么神奇?


从MSDN看到,调用这个方法会返回一个 IEnumerable<T> 对象,而大家知道,和IQueryable比较起来,IEnumerable<T>是用了LINQ2Object的方式,而不是LINQ2SQL的方式,前者数据是在内存中处理的,而后者是在server上运行的。换句话说,本地数据源用IEnumerable<T>,数据在内存中,并且查询的逻辑可以直接用你所定义的方法的逻辑(因为有上下文);远程数据源用IQueryable<T>,无法直接使用你所定义的方法的逻辑,必须先生成表达式树,查询由源对象处理;IQueryable<T>类型可以在最终的执行前加一些方法,然后再返回最终的IQueryable<T>;而IEnumerable<T>已经包含了你执行查询后的所有结果,这时你的添加方法都是在已经有的结果集里进行。一言以蔽之,上面的2100的问题解决方法就是避免了LINQ2SQL生成表达式树查询远程服务器!

这个方法有个副作用:调用dataContext.GetTable<MyEntity>().AsEnumerable()的副作用是吃内存,如果这个table很大,估计内存空间会消耗很大。

此外,调用AsEnumerable()会导致Enumerable.Where运行,而不是原生的.Where运行,看个例子:

复制代码
1 public class ProductList : List<Product>
2 {
3 public IEnumerable<Product> Where(Func<Product, bool> predicate)
4 {
5 Console.WriteLine("Got Here");
6 foreach (var product in this)
7 {
8 if (predicate(product))
9 {
10 yield return product;
11 }
12 }
13 }
14 }
15
16
17 var products = productList
18 .Where(p => p.Name.Contains(productName))
19 .ToArray();
20
21  //Console输出 “Got Here”
22  
23 var products = productList
24 .AsEnumerable()
25 .Where(p => p.Name.Contains(productName))
26 .ToArray();
27  //Console没有输出
复制代码

posted on   Mainz  阅读(2434)  评论(3编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述

统计

点击右上角即可分享
微信分享提示