簡體   English   中英

C# IQueryable LINQ 使用 null 值分組

[英]C# IQueryable LINQ Group By with null values

我想 select 基於一個屬性從數據庫中區分值,當該屬性為null時返回所有值。 我的數據庫中的IDsStrings

我的數據庫如下所示:

Id1   Id2    Value
____________________
1     null   Value1
2     1      Value2
3     1      Value3
4     null   Value4
5     null   Value5
6     2      Value6
7     2      Value7
8     2      Value8

我想從我的查詢中獲取 output ,如下所示:

Id1   Id2    Value
____________________
1     null   Value1
2     1      Value2  // i dont care which one from Id2 = 1 i get
4     null   Value4
5     null   Value5
6     2      Value6  // i dont care which one from Id2 - 2 i get

如您所見,我想獲得一個List ,其中包含Id2為 null 的所有元素,並且只返回一個Id2相同的元素(我不關心將返回哪個元素查詢)。

我試圖編寫一些代碼:

query
   .Where(x => !string.IsNullOrEmpty(x.Id2))
   .GroupBy(z => z.Id2)
   .Select(grp => grp.FirstOrDefault())
   .ToListAsync();

但我沒有得到我想要的,只有一個由Id2表示的項目,只有一個null值,如下所示:

Id1   Id2    Value
____________________
1     null   Value1
2     1      Value2  // I want to get all elements where Id2 = null
6     2      Value6  // and distinct elements based on Id2

我的問題是,如何向 EF 編寫查詢以獲取所有 null 項目和所有基於屬性的不同項目?

未經測試:

var result = query.Where(x => x.Id2 == null || !query.Any(y => y.Id2 == x.Id2 && string.Compare(y.Id1, x.Id1) < 0))

這應該會為您提供Id2 is null的所有行,並且只有每組Id2具有最小Id1的行

在您的 GroupBy 之后,您有一個組序列。 該組的 Key 是 Id2 的值。

如果 Key (Id2) 不是 null,則您只需要該組的一個元素,您不在乎哪一個。

如果 Key 等於 null,則需要該組的所有元素。

有兩種方法可以做到這一點:

  • 對所有非空元素執行 GroupBy
  • 將其與 null 元素連接

或者:

  • 使用 GroupBy 的參數 ResultSelector 來檢查 Key 是否為 null 和 select 要么只有一個元素,要么是組的所有元素

連接方法

IQueryable<MyClass> source = dbContext....

// the elements with non-null Id2, keep only one element:
IQueryable<MyClass> filledId2 = source
    .Where(item => item.Id2 != null)
    .GroupBy(item => item.Id2,

        // Parameter ResultSelector, take Id2 (key) and all items with this Id2
        // to make one new:
        (key, itemsWithThisKey) => itemsWithThisKey.FirstOrDefault());

注意:不會有任何空組,因此結果中沒有“默認”項目。

具有 null Id2 的元素:

IQueryable<MyClass> emptyId2 = source.Where(item => item.Id2 == null);

連接:

var result = filledId2.Concat(emptyId2);

注意:尚未執行任何查詢。 如果需要,您可以創建一個大的 LINQ 語句。 這不會提高效率。 然而,它會降低可讀性。

結果參數方法

   IQueryable<MyClass> filledId2 = source.GroupBy(item => item.Id2,

       // resultSelector: if the key is null, select all elements of the group
       // otherwise select a sequence of one element of the group
       (key, itemsWithThisKey) => (key == null) ? 
             itemsWithThisKey : itemsWithThisKey.Take(1))

       // result: a sequence of sequences of MyClass objects
       // use SelectMany to make it one sequence of MyClass objects:
       .SelectMany(group => group);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM