zoukankan      html  css  js  c++  java
  • 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没有输出
  • 相关阅读:
    用户代理检测浏览器、引擎、平台、设备、游戏系统
    浏览器检测
    js 实现table每列可左右拖动改变列宽度 【转载】
    检测flash是否安装及版本号
    高亮显示搜索的关键词(二)
    修改鼠标选中文本的样式
    高亮显示搜索的关键词
    让站长在SEO时更得心应手的六个细节
    JQuery图片延迟加载插件,动态获取图片长宽尺寸
    jquery 图片背景透明度(支持IE5/IE6/IE7)
  • 原文地址:https://www.cnblogs.com/Mainz/p/1971113.html
Copyright © 2011-2022 走看看