【问题标题】:dynamic LINQ query动态 LINQ 查询
【发布时间】:2011-06-13 09:49:54
【问题描述】:

您好,我正在使用动态 linq,使用 LinqKit 的 PredicateBuilder。

如果您查看代码,在 TODO 注释之后的行,我想完成类似的事情 假设在 objectList 即有 2 个对象。对象1,对象2 (object1.property1 AND object1.property2) OR (object2.property1 AND object2.property2)

我知道 TODO 之后的行不正确,但我正在寻找该行的正确版本。

var finalPredicate = PredicateBuilder.True(); foreach(objectList 中的变量项) { var predicate = PredicateBuilder.True(); predicate = predicate.And (p => p.Description.Contains (item.property1)); predicate = predicate.And (p => p.Description.Contains (item.property2)); //去做: finalPredicate = finalPredicate.Or(predicate); } }

【问题讨论】:

  • 这是最终谓词:` finalPredicate{f => (True OrElse Invoke(f => (((True AndAlso Invoke(p => p.ef.Contains(value(Service1+ c__DisplayClass2 ).item.FilterDomain), f)) AndAlso Invoke(p => p.fname.Contains(value(Service1+ c__DisplayClass2).item.ff), f)) AndAlso Invoke(p => p.subject.Contains( value(Service1+ c__DisplayClass2).item.fs), f)), f))}System.Linq.Expressions.Expression> `
  • 这是错误消息:参数“f”未绑定在指定的 LINQ to Entities 查询表达式中。

标签: .net sql wpf linq


【解决方案1】:

所以前几天我从其他 stackoverflow 问题中找到了解决方案,很抱歉我现在没有指向该帖子的链接,但这就是解决方案

在谓词中使用谓词时,每次都必须 Expand() 。请参阅 TODO 的下一行进行修复。这解决了我的问题。

还修复了真假问题,但这是逻辑错误。

var finalPredicate = PredicateBuilder.False(); foreach(objectList 中的变量项) { var predicate = PredicateBuilder.True(); predicate = predicate.And (p => p.Description.Contains (item.property1)); predicate = predicate.And (p => p.Description.Contains (item.property2)); //去做: finalPredicate = finalPredicate.Or(predicate.Expand()); } }

【讨论】:

    【解决方案2】:

    finalPredicate 不应该以 False 开头吗?这将始终评估为 true。


    编辑:

    看了你发布的异常代码,我想你可以把它非常大致认为是:

    (伪代码)

    finalPredicate = 
        true || 
        (true && 
            p.ef.Contains(item.FilterDomain) && 
            p.fname.Contains(item.ff) && 
            p.subject.Contains(item.fs)
        )
    

    请注意,这不是它真正的意思;您正在构建一个表达式树,它与经典的命令式 C# 不同(所以这个编辑可能是在乞求反对票)。但这可能会让你更容易这样想。

    所以你这里至少有两个问题:

    • 我和其他人指出的是第一个true || ...。真正的价值 ||任何事情都会产生 True。因此,如果您将finalPredicate 初始化为 True,那么无论如何,整个事情都会为 True。事实上,your other expressions might not even get evaluated,这就是为什么只有在将finalPredicate 初始化为 False 时才会看到这个异常的原因。这是您的代码唯一一次受到攻击。
    • 您可能在for 循环中的某个地方有一个错误,我猜它与那些对Contains 的调用有关。但是,如果不进一步了解您的情况或所涉及的数据,就很难说出更多信息。

    希望这会有所帮助。

    【讨论】:

    • And - 以 True 开头,或 - 以 False 开头。对吗?
    • @NSingla - 正确,如果你的意思是我认为你的意思。但是 finalPredicate 只使用了Or 方法。您的子谓词是 And 正在运行的子谓词。
    • finalPredicate{f => (True OrElse Invoke(f => (((True AndAlso Invoke(p => p.ef.Contains(value(Service1+ c__DisplayClass2).item.FilterDomain), f)) AndAlso Invoke(p => p.fname.Contains(value(Service1+ c__DisplayClass2).item.ff), f)) AndAlso Invoke(p => p.subject.Contains(value(Service1+ c__DisplayClass2) .item.fs), f)), f))}System.Linq.Expressions.Expression>
    • 这是错误消息:参数“f”未绑定在指定的 LINQ to Entities 查询表达式中
    【解决方案3】:
    var finalPredicate = PredicateBuilder.True();
    

    应该是

    var finalPredicate = PredicateBuilder.False();
    

    真或 x = 始终为真(x 被忽略)。

    错误或 x = x。


    另一个问题是循环变量在 lambda 表达式中的捕获方式。

    foreach (var item in objectList)
    {
      var loopItem = item;
      //now use loopItem instead of item.
      ...
    }
    

    【讨论】:

    • @David,谢谢。但我收到此错误:参数“f”未绑定在指定的 LINQ to Entities 查询表达式中。
    • 数据 = abc.AsExpandable().Where(finalPredicate).ToList();
    • @NSingla,该异常究竟是在哪里引发的?只有当finalPredicate 被初始化为false 并且for 循环运行不止一次时,你才会得到它?我认为该异常是由for 循环中的某些内容引起的,但问题代码未在您的版本中进行评估,因为true or x 结构在x 之前发生短路(我希望在我写的时候是有道理的)。我不太了解 PredicateBuilder 无法确定这一点,但这是我的第一个想法。
    • @Justin,在这一行 data = abc.AsExpandable().Where(finalPredicate).ToList();
    • @NSingla 好的,这是有道理的。该行是数据实际通过您构建的表达式的位置。在此之前,它只会作为表达式树存在。所以我认为问题不在于第一行或finalPredicate = finalPredicate.Or(predicate);,而是与您要折叠的子表达式有关。不幸的是,我对 PB 的了解不足以知道该异常,所以到目前为止我可以带你去。
    猜你喜欢
    • 2016-10-16
    • 1970-01-01
    • 2011-07-05
    • 2021-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-01
    相关资源
    最近更新 更多