C# IQueryable LINQ Group By с нулевыми значениями - PullRequest
0 голосов
/ 23 апреля 2020

Я хочу выбрать отдельные значения из базы данных на основе одного свойства с возвращенными всеми значениями, когда это свойство равно null. IDs в моей базе данных: Strings

Моя база данных выглядит так:

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

Я хочу получить вывод из моего запроса следующим образом:

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 равен нулю, и возвращает только один элемент, где 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, чтобы получить все нулевые элементы и все отдельные элементы на основе свойства?

Ответы [ 2 ]

1 голос
/ 23 апреля 2020

После вашего GroupBy у вас есть последовательность групп. Ключом группы является значение Id2.

Если ключ (Id2) не равен нулю, вам нужен только один элемент группы, вам безразлично какой.

Если Ключ равен нулю, вам нужны все элементы группы.

Есть два способа сделать это:

  • Сделать GroupBy для всех ненулевых элементов
  • Согласуйте его с нулевыми элементами

Или:

  • Используйте параметр ResultSelector объекта GroupBy, чтобы проверить, является ли ключ нулевым или нет, и выберите либо только один элемент или все элементы группы

Метод конкатенации

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());

Примечание: пустых групп не будет, поэтому в результате нет элементов "по умолчанию".

Элементы с нулевым Id2:

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

Объединение:

var result = filledId2.Concat(emptyId2);

Примечание: запрос еще не выполнен. При желании вы можете создать один большой оператор LINQ. Это не улучшит эффективность. Однако это ухудшит читабельность.

ResultParameter метод

   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);
1 голос
/ 23 апреля 2020

Не проверено:

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, и только к строке с минимумом Id1 для каждой группы Id2

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...