【问题标题】:Loop over parameters to generate LINQ at runtime循环参数以在运行时生成 LINQ
【发布时间】:2011-07-22 04:43:47
【问题描述】:
public class Command
{
    public int CommandId { get; set; }
    public string Title { get; set; }
    public virtual ICollection<CommandPart> CommandParts { get; set; }
}

public class CommandPart
{
    public int CommandPartID { get; set; }
    public string part { get; set; }
    public virtual ICollection<Command> command { get; set; }
}

public ViewResult Filter(string myString)
{
    var foo = myString.Split(Convert.ToChar("+"));
    var a = foo[0];
    var b = foo[1];

    var query =
    db.Commands.Where(
        c =>
        c.CommandParts.Any(p => p.part == a) 
        && (c.CommandParts.Any(p2 => p2.part == b))).ToList();

    return View(query.ToList());
}

当 foo 中恰好有两个项目时,上面的查询按预期工作。我希望能够遍历 foo 来创建查询。这是我的尝试,但它不起作用:

        var foo = myString.Split(Convert.ToChar("+"));
        IQueryable<Command> query = db.Commands;

        foreach (var keyword in foo)
        {
            query = query.Where(c => c.CommandParts.Any(p => p.part == keyword));
        }

这是一个使用实体框架的 ASP.NET MVC3 项目。如何编写查询以便在运行时生成?

【问题讨论】:

标签: c# linq entity-framework


【解决方案1】:

看看PredicateBuilder。它是一个封装了一些 LINQ 表达式的小助手类,允许您动态构建 Where 谓词子句。您可以将 AND 和 OR 子句放在一起,并将它们嵌套得很深。

所以你可以做这样的事情(伪代码):

var predicate = PredicateBuilder.True<Command>(); //use True for ANDs
foreach(var keyword in foo) {
  predicate = predicate.And(c => c.CommandParts.Any(p => p.part==keyword));
}
var results = db.Commands.Where(predicate);

我错过了您正在使用 EF,因此您需要下载 LINQKit(您也可以下载的 NuGet),并使用其“AsExandable”扩展程序。请参阅 PredicateBuilder 页面了解此内容(大约一半)。

希望这会有所帮助!

【讨论】:

  • 谢谢,@david-hoerster 成功了。我确实必须将关键字分配给 foreach 循环内的字符串变量,然后在谓词创建语句中分配引用该变量。我不明白为什么它会起作用,并将发布一个后续问题。
  • 很高兴我能帮上忙。将关键字分配给临时变量是我忘记的。谓词不会立即评估...仅在迭代时,因此不会复制关键字的值;只是对关键字的引用。查找 linq 的延迟执行。这应该可以解释。
猜你喜欢
  • 2017-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-27
  • 2021-09-03
  • 1970-01-01
  • 2015-01-07
  • 1970-01-01
相关资源
最近更新 更多