【问题标题】:How do I prevent multiple results when condition is null for a LINQ query?当 LINQ 查询的条件为空时,如何防止出现多个结果?
【发布时间】:2015-09-18 11:25:43
【问题描述】:

假设以下两个SQL表。

db.Fruits

ID  Name
F1  Apple
F2  Orange
F3  Melon

db.Attributes

ID  Fruits_ID   AttributeType   AttributeValue
A1  F1          Color           Red
A2  F3          Size            Large
A3  F2          Size            Small
A4  F1          Size            Small
A6  F3          Color           Brown

如何使用 LINQ 查询在多个可为空的条件下搜索我想要的水果,而不因 JOIN 导致结果相乘?例如,如果condition 为空,则以下查询会产生多个结果。

var q = from f in db.Fruits
        join a in db.Attributes
        on f.ID equals a.Fruits_ID
        where string.IsNullOrEmpty(condition) || fa.AttributeValue.Contains(conditon)
        select FruitResult
        {
            // ...
        }

无论如何,我也调查过INTO,但这对我不起作用。

var q = from f in db.Fruits
        join a in db.Attributes
        on f.ID equals a.Fruits_ID
        into FruitsAttributes

        from fa in FruitsAttributes
        where string.IsNullOrEmpty(condition) || fa.AttributeValue.Contains(conditon)
        select FruitResult
        {
            // ...
        }

condition 为空或为空时,上面仍然返回多个/连接的结果。

TL;DR:如何在查询中使用一对多 .Contains 签入,以便在条件为空时返回单个“未连接”行?

【问题讨论】:

  • 我不太确定 condition 应该是什么。我认为您应该合并 2 个查询,一个用于 condition != null,一个不与 condition == null 连接的查询。例如var q1 = from f in db.Fruits join a in db.Attributes on f.ID equals a.Fruits_ID where !string.IsNullOrEmpty(condition) || fa.AttributeValue.Contains(conditon) select FruitResult { // ... }; var q2 = from f in db.Fruits where string.IsNullOrEmpty(condition) select FruitResult { // ... }; var q = q1.Union(q2);

标签: c# linq linq-to-sql


【解决方案1】:

你可以试试这个查询:

var q = from f in db.Fruits
                join a in db.Attributes
                on f.Id equals a.FruitId
                into g
                select new FruitResult
                {
                    Id = f.Id,
                    Name = f.Name,
                    Attribute = condition != null ? g.FirstOrDefault(a => a.AttributeValue.Contains(condition)) : null
                };

你可以很方便的在select中扩展retrievieng的属性值,我不知道你需要什么,所以就保持原样了。

【讨论】:

    【解决方案2】:

    如果condition 为空,我猜你期待一个空集,因为它不匹配任何属性?最简单的方法是单独处理这种情况。

    IEnumerable<FruitResult> q;
    if (!string.IsNullOrEmpty(condition))
    {
        q = from f in db.Fruits
            join a in db.Attributes
            on f.ID equals a.Fruits_ID
            where fa.AttributeValue.Contains(conditon)
            select FruitResult
            {
                // ...
            }
    }
    else
    {
        q = Enumberable.Empty<FruitResult>();
    }
    

    【讨论】:

    • 其实恰恰相反。条件为空白应该像一个包罗万象的,即返回所有行。我在这里尝试的是避免由于加入而返回多行。
    【解决方案3】:

    终于找到答案了。它实际上很简单,只需要创建一个过滤器并跳过连接。

    var qFilter = from a in db.Attributes
                  where a.AttributeValue.Contains(condition)
                  select a.Fruits_ID
    
    var q = from f in db.Fruits
            where string.IsNullOrEmpty(condition) || qFilter.Contains(f.ID)
            select FruitResult
            {
                // ...
            }
    

    【讨论】:

      猜你喜欢
      • 2020-02-15
      • 1970-01-01
      • 2015-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-25
      • 2022-01-15
      • 2022-12-01
      相关资源
      最近更新 更多