2012-04-16 6 views
1

Я работаю над проектом MVC. Мне нужно вернуть объект, который группирует пункты меню в группы из четырех, чтобы отображать в представлении, используя foreach-итерацию. Поскольку это модель, передаваемая в представление, мне нужно вернуть не-общий класс коллекции, который может быть привязан к .cshtml.Как использовать LINQ для возврата результата запроса в словарь

Моя мысль состоит в том, что я мог бы группировать список на основе некоторого типа подсчета в LINQ, чтобы добавить четыре новых элемента списка к каждому словарному ключу. Однако я не нашел выражения, которое было бы достаточно для Словаря. Я мог бы решить это довольно легко, создав еще один метод и повторив снова через коллекцию, чтобы назначить ключи на основе подсчета, но это похоже на ненужную итерацию и неправильную практику.

В настоящее время я работаю со следующим запросом.

 var itemsDict = rssDataContext.rss_Application_Blog_Category_Relationships 
      .Where(x => x.Application_Blog.rss_Application.ID == 1) 
      .Where(x => x.Blog_Category_ID == 1) 
      .Select(x => new MenuItem 
      { 
      Name = x.rss_Application_Blog.Blog_Title, 
      Uri = x.rss_Application_Blog.Blog_Uri, 
      ID = x.rss_Application_Blog.ID 
      }); 

Но есть способ сгруппировать этот запрос в группы 4 класса, которые будут заселены в словарь < междунар, Список <MenuItem> >?

+0

Это не для меня ясно, что ключ здесь. Я уверен, что ToDictionary (или ToLookup) сделает это легко, но трудно привести пример, не понимая, что вы пытаетесь сделать. «Некоторый тип счета» довольно расплывчатый. –

+0

По сути, мне нужно сгруппировать запрос в группы по 4, поэтому в каждом подсписке содержится 4 элемента списка, но я не могу вернуть это в общий тип. Следовательно, он должен быть возвращен к типу коллекции, который будет содержать много подписок. – bkingdev

+0

«Поскольку это модель, передаваемая в представление, мне нужно вернуть не общий набор классов« почему? вы можете использовать общие типы для представлений (пока они не открыты. Например, вы можете использовать 'IGrouping >', но не 'IGrouping ' –

ответ

2

@ Решение JonSkeet довольно хорошее. Вот альтернативная реализация с использованием GroupBy для создания подсписки и ToDictionary проецировать их в конечный результат:

var itemsDict = rssDataContext.rss_Application_Blog_Category_Relationships 
    .Where(x => x.Application_Blog.rss_Application.ID == 1) 
    .Where(x => x.Blog_Category_ID == 1) 
    .ToArray() 
    .Select((x, index) => new 
     { 
      Index = index, 
      Item = new MenuItem 
      { 
       Name = x.rss_Application_Blog.Blog_Title, 
       Uri = x.rss_Application_Blog.Blog_Uri, 
       ID = x.rss_Application_Blog.ID 
      } 
     }); 
    .GroupBy(i => i.Index/4) 
    .ToDictionary(g => g.Key); 

Полученная последовательность будет выглядеть примерно так:

items = new Dictionary<int, IGrouping<int>>() 
{ 
    0, new[] 
    { 
     new { Index = 0, Item = new MenuItem { ... } }, 
     new { Index = 1, Item = new MenuItem { ... } } 
    } 
    1, new[] 
    { 
     new { Index = 2, Item = new MenuItem { ... } }, 
     new { Index = 3, Item = new MenuItem { ... } } 
    } 
}; 
+0

Я ценю помощь от всех. Это также исключает NotSupportedException. – bkingdev

+0

Вы добавили 'ToArray()' или 'ToList()' после последнего метода 'Where (...)'? –

3

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

var itemsDict = rssDataContext.rss_Application_Blog_Category_Relationships 
    .Where(x => x.Application_Blog.rss_Application.ID == 1) 
    .Where(x => x.Blog_Category_ID == 1) 
    .Select(x => new { 
     x.rss_Application_Blog.BlogTitle, 
     x.rss_Application_Blog.BlogUri, 
     x.rss_Application_Blog.ID 
    }) 
    .AsEnumerable() // Do the rest of the query in-process 
    .Select((value, index) => new { value, index }) 
    .ToLookup(pair => pair.index % 4, 
       pair => new MenuItem { 
       Name = pair.value.Blog_Title, 
       Uri = pair.value.Blog_Uri, 
       ID = pair.value.ID 
       }); 

Обратите внимание, что это возвращает Lookup, а не Dictionary, но это на самом деле ближе модель для того, что вы хотите.

+0

К сожалению, указанный выше запрос выдает исключение NotSupportedException из-за неподдерживаемой перегрузки оператора select. – bkingdev

+0

Это потому, что тип, возвращаемый свойством 'rss_Application_Blog_Category_Relationships', является' IQueryable', а основной поставщик LINQ * не поддерживает проекцию *. Вам нужно будет загрузить исходную последовательность в памяти, прежде чем применять 'Select', добавив' ToArray() 'или' ToList() '. Например:' .Where (x => x.Blog_Category_ID == 1) .ToArray(). Выберите (...) ' –

+0

@bkingdev: Хорошо, отредактирует для этого ... (Сделано). –