Linq to sql 使用谓词生成器的LinqKit堆栈溢出异常

Linq to sql 使用谓词生成器的LinqKit堆栈溢出异常,linq-to-sql,Linq To Sql,我正在用LINQ和LINQKit用C编写一个应用程序。我有一个很大的数据库表,里面有公司注册号 我想执行LINQ查询,该查询将生成等效的SQL: 从表1中选择*,其中regno位于'123','456' “in”条款可能有数千个术语 首先,我从诸如Country之类的字段获取公司注册号 然后,我将所有公司注册号添加到谓词: var predicate = PredicateExtensions.False<table2>(); if (RegNos !

我正在用LINQ和LINQKit用C编写一个应用程序。我有一个很大的数据库表,里面有公司注册号

我想执行LINQ查询,该查询将生成等效的SQL: 从表1中选择*,其中regno位于'123','456' “in”条款可能有数千个术语

首先,我从诸如Country之类的字段获取公司注册号

然后,我将所有公司注册号添加到谓词:

        var predicate = PredicateExtensions.False<table2>();
        if (RegNos != null)
        {
            foreach (int searchTerm in RegNos)
            {
                int temp = searchTerm;
                predicate = predicate.Or(ec => ec.regno.Equals(temp));
            }
        }
在Windows Vista Professional上,添加4063个术语后发生堆栈溢出异常。在Windows Server 2003上,添加约1000个术语后发生堆栈溢出异常。为了演示,我必须快速解决这个问题

为了解决这个问题,我使用了以下符号:

        var predicate = PredicateExtensions.False<table2>();
        if (RegNos != null)
        {
            predicate = predicate.Or(ec => RegNos.Contains(ec.regno));
        }
我的问题是:

为什么使用foreach循环会发生堆栈溢出

我认为Windows Server 2003的每个进程\线程的堆栈比NT\2000\XP\Vista\Windows 7工作站版本的Windows要小得多

使用LINQ和LINQKit实现这一目标的最快和最正确的方法是什么


有人建议我停止使用LINQ,回到动态SQL或ADO.NET,但我认为使用LINQ和LINQKit在可维护性方面要好得多。

这里有几个问题。首先,《封底之下的L2S》使用sp_execsql,一种SQL自定义项。SQL UDF最多可以传递2100个参数,IIRC、常量和比较符始终作为参数发出。因此,即使表达式计算器没有死,结果查询也不会运行。表达式求值器可能已死亡,因为PredicateBuilder嵌套了添加的表达式,而L2S表达式求值器正在递归地遍历表达式树。也许你可以把这个大的过滤器列表塞进一个临时表,然后加入它?我相信设计器支持命名临时表,或者您可以使用表值存储过程来插入筛选值,然后使用L2S来完成繁重的工作。

正如Matt已经说过的,您的表达式树可能太大了。在我的博客文章中看到你如何处理这个问题


很老的问题,但是。。。LinqKit将使用递归,堆栈将非常深:

OR(OR(OROR(OR(OR(OR(....)))))))
如果您的表达式在列表中,LinqKit有一个AggregateBalanced扩展方法,它将以二叉树的形式平衡表达式:

OR(OR(OR(...), OR(...)),OR(OR(...), OR(...)))
所以在迭代之前调用它,递归级别更像logn而不是n