2015-10-27 3 views
-2

данных, что мой список сворачивается выглядит так:Linq выберите строку на группу, которая содержит мульти идентификаторы

ID | Name  | TypeId | CategoryId | 
----------------------------------------- 
1 | Rows1  | 10  | 1   | 
2 | Rosw2  | 20  | 1   | 

3 | Rosw3  | 30  | 2   | 
4 | Rosw4  | 20  | 2   | 

5 | Rosw5  | 10  | 3   | 
6 | Rosw6  | 10  | 4   | 

7 | Rows7  | 10  | 1   | 
8 | Rosw8  | 20  | 1   | 

Я бы получить только те группы, которые TypeID 10 и 20 (логика и состояние) и не те, у которых разные элементы.

Мой теоретический результат

ID | Name  | TypeId | CategoryId | 
----------------------------------------- 
1 | Rosw1  | 10  | 1   | 
2 | Rosw2  | 20  | 1   | 
5 | Rosw5  | 10  | 3   | 
6 | Rosw6  | 10  | 4   | 
7 | Rows7  | 10  | 1   | 
8 | Rosw8  | 20  | 1   | 

В моих деталях программного обеспечения для фильтрации может быть даже больше, чем два (10,20). Они могут быть от 1 до n.

моих группы состоят из TypeID и CategoryId

Я использую C# на против экспресса.

Прошу прощения за мой английский.

+1

Да так, некоторые 'Where()' и 'Содержит()' магия поможет вам долгий путь. Что вы пробовали? – CodeCaster

+0

Но Содержит Он не использует логический или? – BruceStackOverFlow

+0

'Contains' использует все, что вы пишете в нем. Если вы хотите использовать или использовать '||' то же самое с 'Where'. Они принимают выражение для оценки –

ответ

0

Это звучит, как вы хотите, чтобы foliowing

List<int> types = new List<int>{ 10, 20 }; 
var query = db.Table 
    .Where(x => types.Contains(x.TypeId)) 
    .GroupBy(x => x.CategoryId) 
    .Where(grp => types.All(t => grp.Any(x => x.TypeId == t))) 
    .SelectMany(grp => grp); 

Сначала это отфильтровывает те строки, которые не имеют TypeId из 10 или 20. Затем он группируется на CategoryId. Затем он отфильтровывает группы, у которых нет хотя бы одной строки с TypeId из 10 и 20. Наконец, она выравнивает оставшиеся группы.

Я не уверен на 100%, что EF или любой другой поставщик Linq, который вы используете, понравится этому. Возможно, вам придется поставить AsEnumerable() после GroupBy.

Альтернатива, которая не использует List<int> и должны быть совместимы с EF бы

var query = db.Table 
    .Where(x => x.TypeId == 10 || x.TypeId == 20) 
    .GroupBy(x => x.CategoryId) 
    .Where(grp => grp.Any(x => x.TypeId == 10) && grp.Any(x => x.TypeId == 20)) 
    .SelectMany(grp => grp); 
+0

похоже работа! теперь текст навсегда – BruceStackOverFlow

+0

Я не могу понять эту часть . Где (Grp => types.All (t => grp.Any (x => x.TypeId == t))) – BruceStackOverFlow

+0

@BruceStackOverFlow Это сохраняет группы, когда все типы существуют в любой из групп. В принципе, 'All' возвращает' true', если содержащийся в нем лямбда-оператор является 'true' для всех значений в' types'. Тогда 'Any' вернет' true', если содержащаяся лямбда возвращает 'true' для хотя бы одной из строк в 'grp'. – juharr

0

Вы можете использовать анонимные типы группировать по нескольким свойствам/колонок:

List<int> types = new List<int>{ 10, 20 }; 
var query = db.Table 
    .Where(x => types.Contains(x.TypeId)) 
    .GroupBy(x => new{ x.TypeId, x.CategoryId }) 
    .Select(g => g.First()); 
+0

Это не вернет строки 7 и 8, но вернет 4-ю строку. Основываясь на комментариях ОП, я не считаю, что это правильно. – juharr