2014-01-12 3 views
0

У меня есть запрос linq, который выполняет aggreagtion на объекте контекста db.Linq агрегированное отложенное выполнение, вызывающее запрос для назначения

var filterRange = from row in db.Venues 
         group row by true into r 
         select new 
         { 
          minRent = r.Min(x => x.Rent), 
          maxRent = r.Max(x => x.Rent), 
          minCapacity = r.Min(x => x.Capacity), 
          maxCapacity = r.Max(x => x.Capacity) 
         }; 

ViewBag.mr = filterRange.Select(x => x.minRent); 
ViewBag.xr = filterRange.Select(x => x.maxRent); 

Во время рендеринга бритвы mr и xr в viewbag возникают запрос вместо значений.

Посмотреть

<input type="hidden" id="mr" name="mr" value="@(ViewBag.mr)" /> 

Что нужно сделать, чтобы иметь viewbag флуда значения?

+1

Просьба пояснить _ «с запросом вместо значений» _. Вы можете просто захотеть материализовать запросы здесь, например, вызвав на них '.ToList()' или '.FirstOrDefault()' в зависимости от того, что вы пытаетесь сделать. – CodeCaster

+0

@CodeCaster ViewBag.mr содержит SELECT, [GroupBy1]. [A1] AS [С1] ОТ (SELECT \t [Extent1]. [К1] AS [K1], \t MIN ([Extent1]. [А1]) С. [A1] \t ОТ (SELECT \t \t бросок (1, как бит) AS [K1], \t \t [Extent1]. [аренда] AS [A1] \t \t ОТ [DBO]. [Место] AS [ Extent1] \t) AS [Extent1] \t ГРУППА ПО [K1] ) AS [GroupBy1] –

+0

Затем показать лет ур. И, пожалуйста, объясните, что вы хотите вернуть этот запрос. Если вы просто хотите выбрать минимальную и максимальную аренду из всей таблицы (так, два значения), вы должны написать совершенно другой запрос. – CodeCaster

ответ

2

Во-первых (чтобы избежать итерацию той же последовательности дважды), вы должны «материализоваться» в результирующий из общего запроса:

var filterRange = (from row in db.Venues 
         group row by true into r 
         select new 
         { 
          minRent = r.Min(x => x.Rent), 
          maxRent = r.Max(x => x.Rent), 
          minCapacity = r.Min(x => x.Capacity), 
          maxCapacity = r.Max(x => x.Capacity) 
         }).ToList(); 

Далее, вы также должны «материализоваться» в результирующих из полученных запросов :

ViewBag.mr = filterRange.Select(x => x.minRent).ToList(); 
ViewBag.xr = filterRange.Select(x => x.maxRent).ToList(); 

Это будет выполнять «большой» запрос один раз, то «маленькие» те, то работать на полученном результирующем, так это те, очень дешево.

+0

Это вызывает у ViewBag.mr значение System.Collections.Generic.List'1 [System.Decimal] –

+0

Код верный.Очевидно, что есть вызов 'ToString()' где-то (возможно, неявный). Может быть, код вашего представления делает что-то странное? –

+0

Я отлаживал контроллер, чтобы узнать, что нужно сохранить в viewbag, и подтверждает, что значение свойства viewbag установлено в System.Collections.Generic.List'1 [System.Decimal] –

1

Запрос LINQ возвращает IEnumerable, и вам нужно вызвать некоторый метод для перечисления этого списка, чтобы оценить запрос. В этом случае вы должны добавить вызов ToArray после каждого вызова Select.

+0

если я ставлю вызов toarray после каждого вызова select, который вызывает db дважды? Цель агрегирования в одном запросе - уменьшить количество вызовов. –

+1

Если бы вы не сделали что-то подобное в исходном запросе. Томас Уэллер имеет правильную идею, за исключением того, что вы должны называть ToArray, а не ToList. Я вижу, что многие люди называют ToList по умолчанию, но вы должны только называть ToList, если вам нужен общий список. Массив более эффективен, чем List, поэтому вызывайте ToArray по умолчанию и вызывайте ToList только в том случае, если вы планируете добавлять и удалять элементы позже, поэтому вы должны использовать List по массиву в первую очередь. – jmcilhinney

Смежные вопросы