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

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

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

这个查询工作正常,直到你通过一个大的列表(说3000个左右的ID),然后我得到这个错误:

传入的表格数据stream(TDS)远程过程调用(RPC)协议stream不正确。 在这个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()修复了错误,但使查询变慢。 有没有其他方法可以解决这个问题? 非常感谢。

我的解决scheme(指南 – > 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; 

为什么不写在SQL查询和附加你的实体?

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

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

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

你会希望看看LINQKit项目,因为在那里有一个技术来配合这些语句来解决这个问题。 我相信这个想法是使用PredicateBuilder将本地集合分解成更小的块,但是我没有详细回顾这个解决scheme,因为我一直在寻找更自然的方法来处理这个问题。

不幸的是,从微软的反应来看,我的build议是修复这种行为,没有计划为.NET Framework 4.0或甚至后续的服务包提供这个解决scheme。

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

更新:

我已经打开了一些讨论,关于这是要在MSDN论坛上修复LINQ to SQL还是ADO.NET Entity Framework 。 有关这些主题的更多信息,请参阅这些post,并查看我使用XML和SQL UDF提供的临时解决方法。

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

  1. 相交方法
  2. joinID

要获得不在列表中的值,我使用了Except方法或左连接。

在将它们作为parameter passing给由Linq生成的IN语句之前,您总是可以将您的部门列表分成更小的集合。 看这里:

将一个大的IEnumerable分成一个固定数量的项目的更小的IEnumerable