LINQ — Есть ли способ получить значения элементов после группировки без ForEach?

#linq-to-sql #foreach #grouping

#linq-to-sql #foreach #группировка

Вопрос:

У меня есть таблица элементов, которая содержит поле CategoryID. Это FK в таблицу категорий. Я хочу сгруппировать свои элементы по идентификатору категории и вернуть элементы и Categories.Name .

Я знаю, что могу сделать это на C#:

 var ItemsByCat = 
    from i in Items
    group i by i.CategoryId into g
    select g

foreach(var n in ItemsByCat)
{
    blah, blah
}
  

Мой вопрос — есть ли способ получить значения элементов в рамках группировки без необходимости повторять цикл? Что-то вроде:

 from i in Items
group i by i.CategoryId into g
select new {
    CategoryID = g.Key,
    CategoryName = ???,
    Items = ???
}
  

Большое спасибо,

BK

Ответ №1:

Я думаю, это то, что вы ищете:

 from i in Items
group i by i.CategoryId into g
select new 
{
    CategoryID = g.Key,
    CategoryName = g.First().Category.Name,
    Items = g
}
  

РЕДАКТИРОВАТЬ: я надеюсь, что это ответ на ваш вопрос из комментариев.

g это коллекция элементов, сгруппированных по их CategoryId . Items в select может быть проекция, включающая любое подмножество Item свойств, которые вам требуются. Пример:

 from i in Items
group i by i.CategoryId into g
select new 
{
    CategoryID = g.Key,
    CategoryName = g.First().Category.Name,
    Items = g.Select(a => new{a.ItemID, a.ItemName})
}
  

Комментарии:

1. Ах, я понял — значит, g — это коллекция и с помощью . Сначала () я могу просто захватить CategoryName . Большое спасибо!

2. Точно. g — это просто еще один тип коллекции, который реализует IEnumerable . Я рад, что помог.

3. Последний вопрос — что, если элементы в select были коллекцией объектов с элементами. ItemId, Items.Name ? Другими словами, я не хочу возвращать коллекцию целых записей элементов, а только подмножество полей элементов.

4. Я добавил к своему ответу некоторую информацию, которая, как я думаю, отвечает на ваш вопрос. Дайте мне знать.

5. Прямо идеально! Еще раз спасибо.

Ответ №2:

Как насчет объединения в таблицу категорий?

 from i in Items
join c in Categories on i.CategoryId equals c.Id
group i by i.CategoryId into g
select new {
    CategoryID = g.Key,
    CategoryName = c.Name,
    Items = i
}
  

Ответ №3:

CategoryName должно быть i.Category.CategoryName //the name property

учитывая, что у вас есть правильная настройка отношений.

Элементы должны быть значениями group by , не уверен, зачем вам нужно делать это снова.

Комментарии:

1. После группировки i больше не находится в области видимости. Все, с чем мне нужно работать, это g .

2. да, это то, что я имел в виду, значения каждого элемента в g сгруппированы по элементам. Каждая сгруппированная запись имеет ключ и элементы (это ваши элементы, lol)

Ответ №4:

Предполагая, что у вас есть коллекция категорий в переменных categories, это будет выглядеть так:

 var ItemsByCategory = 
  from i in items
  join c in categories on i.CategoryId equals c.Id
  group i by i.CategoryId into g
  select new {
    CategoryId=g.Key,
    CategoryName=c.Name,
    Items=g.Items
}
  

Комментарии:

1. Это предполагает, что вы не используете Entity Framework. В EF вы просто просматриваете свои свойства навигации, объединения не требуются.

2. Я думаю, что c выходит за рамки, как только я выполняю группировку. Если я перемещу объединение ниже группировки и присоединюсь к категориям на c.CategoryID = g.Key, похоже, это сработает. Это хороший подход?

3. Это нормально… Я нахожу странным, что это не работает по-другому, хотя, возможно, так оно и анализируется.