【问题标题】:stating which conditions have been matched in linq where说明在 linq where 中匹配了哪些条件
【发布时间】:2016-05-02 19:45:10
【问题描述】:

我有一个这样的 linq 语句

dbContext.Items   
.Where(
p =>

  (p.Client.Contact != null && p.Client.Contact.Firstname.ToLower().Contains(searchText.ToLower()))
  ||
  (p.Client.Contact != null && p.Client.Contact.Surname.ToLower().Contains(searchText.ToLower()))
  ||
  (p.PolicyNumber != null && p.PolicyNumber.ToLower().Contains(searchText.ToLower()))
  ||
  (
    p.PolicyLivesAssureds
    .Where(
        pl =>
        pl.Contact != null && pl.Contact.Firstname.ToLower().Contains(searchText.ToLower())
        || pl.Contact.Surname.ToLower().Contains(searchText.ToLower())
        ).Count() > 0
  )
)
).OrderBy(p => p.IeUtem);

这实际上是自动完成所需要的。我想要做的是能够准确地知道我的 5 个条件中的哪一个已匹配并显示已匹配的特定项目。例如说 PolicyNumber 已匹配,我只想发送该行的 policynumber,如果名称已匹配,我只想发送该行的名称。

有没有办法做到这一点;

【问题讨论】:

  • 由于您使用的是OR,我建议将其拆分为 5 个单独的查询。这样更容易计算单独组件的结果并将结果存储在专用对象中。不过,由于您使用的是OrderBy,您可能希望在某处再次合并数据。
  • 你使用 C#6.0 吗?如果是这样,某些表达式可以简化为:p.Client.Contact != null && p.Client.Contact.Firstname.ToLower().Contains(searchText.ToLower())p.Client.Contact?.Firstname.ToLower().Contains(searchText.ToLower())

标签: c# sql database linq select


【解决方案1】:

这是一个值得深思的答案,因为它的方法存在缺陷,但我认为它确实解决了您的问题:

double[] items = { 1, 2, 3, 4, 5 };
IEnumerable<Tuple<double, int>> results = items.Select(x =>
    {
        int index = 0;
        foreach (var condition in new Func<bool>[]
            {
                // TODO: Write conditions here.
                () => x == 1,
                () => x == 2
            })
        {
            if (condition() == true)
                return index;
            else
                index++;
        }
        return -1;
    }).Zip(items, (matchedCondtion, item) => Tuple.Create(item, matchedCondtion))
    .Where(x => x.Item2 != -1);

我使用了一个简单的双精度数组作为要过滤的集合的例子,但这只是一个例子,你可以使用任何东西。

第一个选择为集合中的每个元素返回一个整数。如果有条件匹配,则返回条件的索引。如果不匹配,则返回 -1。

它通过枚举 Func 集合并返回第一个真实条件的索引来实现这一点(模拟 || 运算符的短路)。如果没有条件匹配,则在评估所有条件后简单地返回 -1。

然后将这些结果与原始集合一起压缩备份(使用元组),将每个元素映射到其匹配条件的索引(或 -1)。

所以示例会返回:

{ 1, 0 },
{ 2, 1 },
{ 3, -1 },
{ 4, -1 },
{ 5, -1 }

然后使用 Where 简单地过滤此结果以删除任何带有 -1 的条目,从而为您留下与条件匹配的元素集合和匹配条件的索引(以元组的形式)。

因此,要为您的解决方案定制这个,您可以删除示例条件并放置您想要的任意数量的条件:

// TODO: Write conditions here.

【讨论】:

    【解决方案2】:

    问题变成了您想如何知道哪些查询匹配。例如你可以做这样的事情

    class AutoCompleteItem {
        String Text {get; set;}
        Item Item {get; set;}
    }
    
    var firstNames = dbContext.Items.Select(p => new AutoCompleteItem { Name = p.Client.Contract.FirstName, Item = p})
    
    var lastNames =  dbContext.Items.Select(p => new AutoCompleteItem { Name = p.Client.Contract.SurName, Item = p})
    
    var result = firstName.Union(lastNames).Where(p => p.Name.Contains(searchText)).OrderBy(a => a.Item.IeUtem);
    

    现在 AutcompleteItem 是一个包含您想要的文本的类(可能还有您需要的任何其他字段,例如匹配哪个字段的信息)

    这里的想法是 MVVM 模式。你有你的模型(项目)。现在您需要构建一个视图模型(AutoCompleteItems)来实际帮助您显示您想要的内容。

    【讨论】:

    • 我可以做三个查询,但是我的数据库调用数量有限,我想做一个查询
    • Linq 只会在您实际使用结果时执行您的查询。因此,当您执行最终的 ToList 时,它应该执行整个查询。
    猜你喜欢
    • 1970-01-01
    • 2011-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-02
    • 2020-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多