使用Linq,如何正确附加多个Where子句,以便它们以适当的顺序出现?

时间:2018-10-05 18:25:11

标签: linq

我希望最终结果出现的顺序是“完全匹配”,首先给出一个输入字符串,然后是给定字段包含的其他匹配。我试图以一种非常基本的方式来解决这个问题,如本示例所示:

var raw = Model.SearchResults.Where(m =>  m.EffectiveDateTime != null).OrderBy(m => m.EffectiveDateTime).ToList();
    var exact = raw.Where(m => m.IssueNumber.ToLower() == Model.SearchText.ToLower());
    var contains = raw.Where(m => m.IssueNumber.ToLower().Contains(Model.SearchText.ToLower()));
    var list = exact.Union(contains);

这种方法似乎是一种非常糟糕的方法。实际上,Union部分似乎有效地使我的应用程序崩溃了。与Intersection是否有对立面,它将为我提供完全匹配项之外的其余结果,然后我可以将其附加到最终列表中,从而使顺序为完全匹配项,然后是StartsWith匹配项,最后是包含该降序排列的匹配项?

2 个答案:

答案 0 :(得分:1)

要回答您的原始问题,您可以使用一个临时表达式对匹配类型进行分类,然后按匹配类型和其他条件进行排序,它也将转换为SQL:

var st = Model.SearchText.ToLower();
var list = Model.SearchResults.Where(m => m.EffectiveDateTime != null)
                              .Select(m => new {
                                  m,
                                  im = m.IssueNumber.ToLower()
                              })
                              .Select(mim => new {
                                  mim.m,
                                  Rank = mim.im == st ? 1 : mim.im.StartsWith(st) ? 2 : mim.im.Contains(st) ? 3 : 4
                              })
                              .Where(mr => mr.Rank < 4)
                              .OrderBy(mr => mr.Rank)
                              .ThenBy(mr => mr.m.EffectiveDateTime)
                              .Select(mr => mr.m)
                              .ToList();

我做了两次Select来模仿流利的语法let,在这种情况下,我认为它比lambda语法更清楚:

var lisx = (from m in Model.SearchResults
            where m.EffectiveDateTime != null
            let im = m.IssueNumber.ToLower()
            let Rank = im == st ? 1 : im.StartsWith(st) ? 2 : im.Contains(st) ? 3 : 4
            where Rank < 4
            orderby Rank, m.EffectiveDateTime
            select m)
           .ToList();

此外,如果您在数据库中进行整个查询,则ToLower可能是不必要的,因为SQL的默认值可能不区分大小写。

答案 1 :(得分:0)

实际上,我回到了绘图板上并弄清楚了。这对我来说好一点,并返回我需要的结果。

        var list = Model.SearchResults
             .Where(e => e.A.ToLower().Contains(Model.SearchText.ToLower()))
             .GroupBy(d => new { d.A, d.B, d.C})
             .OrderBy(x => x.Key.A)
             .ThenBy(x => x.Key.B)
             .ThenBy(x => x.Key.C)
             .Select(x => new
             {
                 A= x.Key.A,
                 B= x.Key.B,
                 C= x.Key.C
             })
             .ToList();