实体框架达到2100个参数限制

9
我正在将我们的一些代码从LINQ-to-SQL迁移到Entity Framework。以前,当遇到SQL Server的2100个参数限制(在这里中描述)时,我使用了Marc Gravell在这里提供的解决方案。正如他自己的回答中所述,它不适用于Entity Framework。
我对表达式的经验太少,不知道从哪里开始,但我需要的基本上是相同的扩展方法,但适用于Entity Framework。非常感谢您能提供的任何帮助。

1
创建需要超过2100个静态定义项的查询(即“包含”操作的对应项)似乎不是正确的方法。这种操作应该完全在数据库中处理,而无需从客户端传递数据。 - Ladislav Mrnka
1
我理解您的担忧,但是有些情况下数据库中并不包含所有所需数据。当然,有很多替代方案可以避免传递如此大量的参数,但这种简单的全捕获方法对于我们想要使用它的方式非常灵活(而且99%的时间都不需要使用它)。 - Ocelot20
1个回答

23

在EF中不存在2100个参数限制问题。

我在AdventureWorks数据库(在SQL Express 2008 R2中)上进行了测试:我尝试获取所有ProductCategoryId值在(1、2、3)范围内的产品。

使用LINQ,生成的SQL WHERE子句如下:

WHERE [t0].[ProductCategoryID] IN (@p0, @p1, @p2)
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [1]
-- @p1: Input Int (Size = -1; Prec = 0; Scale = 0) [2]
-- @p2: Input Int (Size = -1; Prec = 0; Scale = 0) [3]

这导致了最大参数数量的问题,而使用EF 4.0则是这样的:

WHERE [Extent1].[ProductCategoryID] IN (1,2,3)

接下来,我已经使用EF测试了3000个值的列表:

var categoryList = Enumerable.Range(1, 3000).Select(i => (int?)i).ToArray();

using (var aw = new AdventureWorksEntities())
{
    var products = aw.Products
        .Where(p => categoryList.Contains(p.ProductCategoryID))
        .ToList();
}

虽然这种方法非常低效,但它能够正常工作并产生预期的结果。

然而,也可以使用由Marc Gravell提供的InRange扩展provided by Marc Gravell与EF一起使用,同时还要使用LINQKit library,如下所示:

using (var aw = new AdventureWorksEntities())
{
    var products = aw.Products
        .AsExpandable()
        .InRange(p => p.ProductCategoryID, 1000, categoryList)
        .ToList();
}

AsExpandable扩展定义在LINQKit中)

这将产生预期的结果(按块执行查询),并且根据列表中项目的数量和块的大小,可以比非分块解决方案更有效率。


有没有一种方法可以为多个参数执行此操作? - user1152145
1
Cristian,感谢您的有用回答! 您写道:“虽然这非常低效,但它可以工作并产生预期的结果。” 请问为什么一次性请求3000个项目非常低效,而分批请求则更高效呢? - Liraz Shay
1
@LirazShay 我现在不记得具体细节了,但我建议为您的特定情况运行一些测试,以了解哪种方法更好。无论如何,如果可能有一个非常大的列表,我会实现分块来避免出现1M值的情况。 - Cristian Lupascu
这个处理程序只针对非常特定的情况,不能作为通用方法重复使用(当查询同时具有过滤器并需要返回下一页时)。 - Cesar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接