【问题标题】:Stackoverflow Exception using PredicateBuilder with Entity Framework使用 PredicateBuilder 和实体框架的 Stackoverflow 异常
【发布时间】:2018-03-22 17:10:20
【问题描述】:

我有谓词构建器,它具有谓词和内部谓词,并根据条件构建动态过滤器,假设我选择一个部门,在该部门下我得到员工列表,一旦我得到员工列表,我需要为属于所选部门的每个员工加载各自的记录。

实施很久以前就已经完成,如果部门没有太多员工,它可以正常工作,一旦超过 500 或 1000,谓词构建器就会导致堆栈溢出。请参阅我的代码 sn-p - 我使用的是 .net framework 4.5.2。

使用in循环在这一行分配给内部谓词时出现stackoverflow异常,当记录超过1000或500时,它会根据员工记录循环。

Expression<Func<EmployeeTable, bool>> predicate =  PredicateBuilder.True<EmployeeTable>();
var innerPredicate = PredicateBuilder.False<EmployeeTable>();

case FilterBy.EmployeeName:
    if (!isEmpNameFilterExists)
    {
        foreach (string empName in item.FieldCollection)
        {
            innerPredicate = innerPredicate.Or(x => x.Name.Equals(empName, 
                                       StringComparison.OrdinalIgnoreCase));
        }
        predicate = predicate.And(innerPredicate.Expand());
    }
    break;

【问题讨论】:

    标签: entity-framework predicatebuilder


    【解决方案1】:

    这可能是由于 .NET 应用程序 (https://stackoverflow.com/a/823729/2298807) 的堆栈(通常足够)但很小。谓词的评估通常作为 lamda 函数的一部分完成,并且它们使用堆栈。我现在不详细介绍谓词库,但我假设使用递归函数。

    无论如何:我建议通过构建一个包含名称的List&lt;string&gt; 来使用Contains

    Expression<Func<EmployeeTable, bool>> predicate =  
    PredicateBuilder.True<EmployeeTable>();
    var innerPredicate = PredicateBuilder.False<EmployeeTable>();
    
    case FilterBy.EmployeeName:
        if (!isEmpNameFilterExists)
        {
            List<string> namesList = new List<string>();
            foreach (string empName in item.FieldCollection)
            {
                namesList.Add(empName);
            }
            predicate = predicate.And(x => namesList.Contains(x.Name));
         }
         break;
    

    注意:请检查语法,因为我目前没有可用的 VS 环境。

    【讨论】:

    • 呵呵...副作用...这可能会导致不区分大小写的搜索出现问题。在这种情况下,您可以考虑查看stackoverflow.com/questions/444798/…
    • Contains 帮助我不在该行引发堆栈溢出异常,但无论我在哪里调用 contxt.EmployeeTable.AsExpandable().Where(predicate) 它的中断
    • 在修复错字后,代码对我有用...由于表中没有任何数据,因此调用 context.EmployeeTable.AsExpandable().Where(predicate) 会返回一个空列表。 打破是什么意思?
    【解决方案2】:

    我添加了自己的表达式构建器引擎,即生成谓词的更好方法。 PredicateBuilder 与 LINQ to Object 配合得很好,而 EntityFramework 则存在问题,因为它生成具有完整模型命名空间的 Lambda 方法,并继续添加多个搜索条件。我觉得它在实体框架中具有大量过滤器的局限性。在我的情况下,我将 728 个计数传递给模型的一个字段,它因堆栈溢出异常而中断。 728 lambdas 方法将使用完整的特定名称空间添加到堆栈中。

    自定义表达式在我的情况下工作得很好。请在下面找到相同的源代码。

    var entityType = typeof(Emptable); var 参数 = Expression.Parameter(entityType, "a"); var containsMethod = typeof(string).GetMethod("Equals", new[] { typeof(string) }); //员工姓名过滤器的切换语句。 案例 FilterBy.EmployeeName: if (!isEmpNameFilterExists) {
    var propertyExpression = Expression.Property(parameter, "EmployeeName"); foreach(item.FieldCollection 中的字符串 empName) { var innerExpression = Expression.Call(propertyExpression, containsMethod, Expression.Constant(empName)); body = Expression.OrElse(body, innerExpression); } } 打破;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多