使用Contains()时达到2100参数限制(SQL Server)

时间:2009-03-17 21:47:17

标签: sql-server linq parameters limit

from f in CUSTOMERS
where depts.Contains(f.DEPT_ID)
select f.NAME

depts是部门ID的列表(IEnumerable<int>

此查询正常工作,直到您传递一个大型列表(比如大约3000个dept ID)..然后我收到此错误:

  

传入的表格数据流(TDS)远程过程调用(RPC)协议流不正确。此RPC请求中提供的参数太多。最高为2100。

我将查询更改为:

var dept_ids = string.Join(" ", depts.ToStringArray());
from f in CUSTOMERS
where dept_ids.IndexOf(Convert.ToString(f.DEPT_id)) != -1
select f.NAME

使用IndexOf()修复了错误但使查询变慢。有没有其他方法可以解决这个问题?非常感谢。

5 个答案:

答案 0 :(得分:12)

我的解决方案(指南 - &gt; Guid列表):

List<tstTest> tsts = new List<tstTest>();
for(int i = 0; i < Math.Ceiling((double)Guides.Count / 2000); i++)
{
    tsts.AddRange(dc.tstTests.Where(x => Guides.Skip(i * 2000).Take(2000).Contains(x.tstGuid)));
}
this.DataContext = tsts;

答案 1 :(得分:7)

为什么不在sql中编写查询并附加你的实体?

自从我在Linq工作以来已经有一段时间了,但是这里有:

IQuery q = Session.CreateQuery(@"
         select * 
         from customerTable f
         where f.DEPT_id in (" + string.Join(",", depts.ToStringArray()) + ")");
q.AttachEntity(CUSTOMER);

当然,你需要防止注射,但这不应该太难。

答案 2 :(得分:1)

您需要查看LINQKit project,因为在某处某处是一种用于批处理此类语句以解决此问题的技术。我相信这个想法是使用PredicateBuilder将本地集合分解成更小的块,但我没有详细检查解决方案,因为我反而一直在寻找一种更自然的方法来处理这个问题。

不幸的是,从Microsoft's response to my suggestion出现了解决此行为的问题,即没有计划为.NET Framework 4.0或后续服务包解决此问题。

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=475984

更新:

我已经就MSDN论坛上的LINQ to SQLADO.NET Entity Framework是否修复了问题进行了讨论。有关这些主题的更多信息,请参阅这些帖子,并查看我使用XML和SQL UDF提出的临时解决方法。

答案 3 :(得分:0)

我有类似的问题,我有两种方法可以解决它。

  1. Intersect方法
  2. 加入ID
  3. 要获取不在列表中的值,我使用Except方法或左连接。

    <强>更新

    EntityFramework 6.2成功运行以下查询:

    var employeeIDs = Enumerable.Range(3, 5000);
    var orders =
        from order in Orders
        where employeeIDs.Contains((int)order.EmployeeID)
        select order;
    

答案 4 :(得分:-1)

在将depts列表作为参数传递给Linq生成的IN语句之前,您总是可以将depts列表分割为更小的集合。见这里:

Divide a large IEnumerable into smaller IEnumerable of a fix amount of item