有没有更好的方法来编写这个linq查询?

时间:2013-05-31 15:14:00

标签: c# linq

我有Asset个实体的列表,每个Asset都有一个Field个实体列表,每个实体都有两个属性,看起来像这样

| Index | Value |
| 0 | "hello" |
| 1 | "blah" |
| 2 | null |

在循环中我得到变量

i = 2i = 3

我有一个linq查询尝试获取以下内容:Assets Field Valuei对应的nullField,或者Index i没有i

例如,如果Field为2,则会返回包含上表的资产,因为它有null,其中2对应i

并且,如果Field为3,则还应返回上述内容,因为Index没有var assets = (from a in assets where a.Fields.Any(x => x.Index == i && x.Value == null) select a) .Union(from a in assets where a.Fields.All(x => x.Index != i) select a) .ToList(); 3。

此代码有效:

{{1}}

这不是很好,我想知道有没有办法在一个声明中做到这一点?

5 个答案:

答案 0 :(得分:7)

其他答案有效,但如果你简化问题,它会变得更加直截了当:

assets.Where(a => !a.Fields().Any(f => f.Index == i &&
                                       f.Value != null))
      .ToList()

您希望所有AssetField的{​​{1}} Indexi非空Value。您无需将其分为两个条件。

答案 1 :(得分:5)

您不需要两个查询,只需使用||

assets = assets
    .Where(a => a.Fields.Any(f => f.Index == i && f.Value == null)
            ||  a.Fields.All(f => f.Index != i))
    .ToList(); 

答案 2 :(得分:1)

我有几个选择,正如我所看到的那样:

  1. 仅对资产ID和索引使用更传统的LINQ和LEFT JOIN JOIN语法。因此,如果LEFT JOIN返回null(即DefaultIfEmpty()),则找不到该资产的索引。那是#2的情况。但是,如果它不为null,那么您可以通过检查whereValue来进一步过滤(即null子句)。那就是#1。
  2. 你可以结合where语句。 where a.Fields.Any(...) || a.Fields.All
  3. 在我看来,您会想要尝试这两种方法,看看哪种方式能更好地满足您的需求。我猜第一个选项会表现得更好,但如果数据量很小,第二个选项肯定要容易得多。

答案 3 :(得分:0)

var assets = assets.where(a => a.Fields.Any(x => x.Index == i && x.Value == null) || a.Fields.All(x => x.Index != i)).ToList();

答案 4 :(得分:0)

在这种情况下,您实际上可以快速查询查询

 var assets = (
                from a in assets
                where a.Fields.All(x => x.Index != i || x.Value == null)
                select a
              ).ToList();