当前位置:主页   - 电脑 - 网站开发 - ASP.Net
LINQ参数过多时的解决方案
来源:网络   作者:   更新时间:2012-08-04
收藏此页】    【字号    】    【打印】    【关闭

  在项目中曾有这样的应用,权限筛选时先组织出员工的id,然后使用LINQ在相应的表中查询数据,条件是这些查询出来的数据的id必须在刚才权限筛选出来的id中,但是如果权限中的id太多,就会出现问题“传入的表格格式数据流(TDS)远程过程调用(RPC)协议流不正确。此 RPC 请求中提供了过多的参数。最多应为 2100”。我推断可能是SQLServer中使用参数不能超过2100的原因。以上描述请看下边的例子。

int[]inputList=newint[2100];
      for(inti=0;i<inputList.Length;i++)
      {
        inputList[i]=i;
      }
      DataClasses1DataContextdc=newDataClasses1DataContext();
      vart=(fromxindc.test1
         selectx).Where(c=>inputList.Contains(c.testID));
      dc.Log=Console.Out;
      foreach(varitemint)
      {
        Console.WriteLine(item.testID);
      }

  运行以上代码会报“传入的表格格式数据流(TDS)远程过程调用(RPC)协议流不正确。此 RPC 请求中提供了过多的参数。最多应为 2100”异常,如果将inputList数组大小改为5,执行的sql如下:

SELECT [t0].[testID], [t0].[testContent], [t0].[p]
FROM [dbo].[test1] AS [t0]
WHERE [t0].[testID] IN (@p0, @p1, @p2, @p3, @p4)

  现在问题是如果超过2100个参数怎么办,我没想出用linq实现的好办法,这里使用了一个折中的办法

publicstaticList<T>test<T>()
    {
      DataClasses1DataContextdc=newDataClasses1DataContext();
      dc.Log=Console.Out;
      int[]inputList=newint[2100];
      StringBuildersqlstr=newStringBuilder("select*from");
      sqlstr.Append(typeof(T).Name);
      sqlstr.Append("wheretestidin(");
      for(inti=0;i<inputList.Length;i++)
      {
        sqlstr.Append(i);
        if(i<inputList.Length-1)
        {
          sqlstr.Append(",");
        }
        else
        {
          sqlstr.Append(")");
        }
      }    
      SqlCommandcmd=newSqlCommand(sqlstr.ToString(),(SqlConnection)dc.Connection);
      dc.Connection.Open();
      SqlDataReaderdr=cmd.ExecuteReader();
      List<T>t=dc.Translate<T>(dr).ToList();
      returnt;
    }
staticvoidMain(string[]args)
    {
    List<test1>l=MyClass.test<test1>();
      foreach(variteminl)
      {
        Console.WriteLine(item.testID);
      }
}

  这里利用了反射得到表名,然后利用Linq中的Translate方法将SqlDataReader转换成相应的类。

  8月11日更新:

  如果inputList不是一个数组而是一个IQueryable,直接用就没什么问题

vartt=(fromxindc.test
           selectx.testid);
      vart=fromxindc.log
          wherett.Contains<int?>(x.logId)
          selectx;
      dc.Log=Console.Out;
      foreach(varitemint)
      {
        Console.WriteLine(item.logMessage);
      }

  拼接出的sql语句如下:

SELECT [t0].[logId], [t0].[logMessage], [t0].[x]
FROM [dbo].[log] AS [t0]
WHERE EXISTS(
  SELECT NULL AS [EMPTY]
  FROM [dbo].[test] AS [t1]
  WHERE [t1].[testid] = ([t0].[logId])
  )

其它资源
来源声明

版权与免责声明
1、本站所发布的文章仅供技术交流参考,本站不主张将其做为决策的依据,浏览者可自愿选择采信与否,本站不对因采信这些信息所产生的任何问题负责。
2、本站部分文章来源于网络,其版权为原权利人所有。由于来源之故,有的文章未能获得作者姓名,署“未知”或“佚名”。对于这些文章,有知悉作者姓名的请告知本站,以便及时署名。如果作者要求删除,我们将予以删除。除此之外本站不再承担其它责任。
3、本站部分文章来源于本站原创,本站拥有所有权利。
4、如对本站发布的信息有异议,请联系我们,经本站确认后,将在三个工作日内做出修改或删除处理。
请参阅权责声明