【问题标题】:How to dynamically add Where and Or statements to a Linq query [duplicate]如何将 Where 和 Or 语句动态添加到 Linq 查询[重复]
【发布时间】:2019-06-14 04:01:01
【问题描述】:

第一次使用 c# 和 Linq。我有一根绳子通过我的路线进来。我想在几个不同的列中搜索字符串中的值。假设我将每个单词拆分为一个空格,foreach 我想动态地将.Where 添加到我的 linq 语句中。我想我可能还需要动态添加.Or

foreach (string q in query)
{
    results = results.Where(u => u.Name.Contains(r));
    results = results.Where(u => u.Text.Contains(r));
}

我已经习惯了 JS,你可以在其中做类似 results += results.Where(...) 的事情,我不确定使用 linq 构建这种事情的适当方法。

编辑:为了清楚起见,这是整个方法

            using (var context = new MessageContext())
        {
            string[] words = query.Split(" ");
            var messages = (from m in context.Messages
                          join u in context.Users on m.UserId equals u.UserID
                          select new
                          {
                              m.Id,
                              m.Date,
                              m.Name,
                              m.Text,
                              m.UserId,
                              u.Image
                          });

            foreach (string word in words)
            {
                messages = messages.Where(u => u.Name.Contains(word)).Union(messages.Where(u => u.Text.Contains(word)));

            return messages.ToList();
        }

【问题讨论】:

  • Or 将成为Where 的一部分,不是吗?喜欢.Where(x => x == "a" || x == "b")
  • 您可以使用Expression Tree,也可以使用Dynamic Linq
  • 但是我该如何防止它覆盖已经包含在results.@John 中的数据
  • @ChristopherMellor John 的示例向您展示了如何操作。不要说results = this,然后是results = that。只需获取一次结果并查找u.Name.Contains(r) || u.Text.Contains(r)。这将创建一个包含所有匹配元素的列表。还有.addRange() - 无论哪种方式都可以,但我会选择1-off查询。
  • @Christopher 你不是在覆盖,而是在链接。 .Where(a => a.Opt1 == true).Where(a => a.Opt2 = false) 等价于 .Where(a => a.Opt1 == true && a.Opt2 == false)

标签: c# .net linq linq-to-sql


【解决方案1】:

Linq 使用惰性求值(在您开始迭代结果或调用 ToList() 之类的方法之前,不会对结果进行求值)。正如约翰指出的那样,每次连续调用实际上只是在修改搜索条件。因此在你的例子中

results = results.Where(u => u.Name.Contains(r));
results = results.Where(u => u.Text.Contains(r));

等价于

results = results.Where(u => u.Name.Contains(r)).Where(u => u.Text.Contains(r));

这意味着 AND 条件。如果您想要 OR 条件,您需要使用 Union 运算符。

results = results.Where(u => u.Name.Contains(r)).Union(results.Where(u => u.Text.Contains(r)));

这种惰性求值的好处是您可以提取基本查询并添加额外的搜索条件,从而简化您的代码。

我希望这会有所帮助。

【讨论】:

  • 感谢您的解释——它澄清了很多。但是,Linq 似乎没有进行您上面提到的惰性评估,但也许我在滥用它。如果您查看上面的编辑,也许您可​​以提供一些见解?当我通过它进行调试时,第一次通过foreach 似乎messages 实际上确实过滤掉了一些消息。到下一次通过 foreach 时,它正在搜索包含查询中第二项的消息,这些消息在已经过滤为包含第一项的消息中......如果这有意义......
【解决方案2】:
foreach (string q in query)
{
   results = results.Where(u => u.Name.Contains(r) || u.Text.Contains(r));
}

或者您可能需要详细说明您的问题

【讨论】:

    猜你喜欢
    • 2010-09-15
    • 2010-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-02
    • 1970-01-01
    • 1970-01-01
    • 2014-12-19
    相关资源
    最近更新 更多