2013-06-26 2 views
0

Я, очевидно, не знаю, что я делаю. Этот материал MVC действительно дует мне в голову, пытаясь сохранить шаблон. Я слежу за учебниками MVC, а также с мега-гуглингом, и это тот уголок, в который я нарисовал себя.Неэффективный MVC ViewModel Создание нескольких вызовов в базе данных?

У меня есть несколько подобных частей данных, которые я пытаюсь получить. Я могу заставить свой код работать, но для меня это выглядит просто неэффективно, так как мы начинаем вытягивать большие записи из db из-за нескольких вызовов в db. Итак, у меня есть класс OrderSummary, внутри класса это:

public IEnumerable<Order> GetOrders() 
{ 
    var orders = (from s in db.Orders 
       where s.UserId == uId 
       select s); 

    return orders.ToList(); 
} 

Тогда это:

public decimal GetGrossProfitTotal() 
{ 
    var orders = (from s in db.Orders 
       where s.UserId == uId 
       select s); 
    decimal? grossprofittotal = orders.Sum(s => s.Profit); 

    return grossprofittotal ?? decimal.Zero; 
} 

Таким образом, если мы примем, что последний кусок кода и скопировать его для totalcommission и netprofittotal, что в основном как у меня все сложилось. Я бы угадал четыре звонка в db?

Тогда в контроллере:

 var ordersummary = new OrdersSummary(); 
     var viewModel = new OrderSummary 
     { 
      Orders = ordersummary.GetOrders(), 
      GrossProfitTotal = ordersummary.GetGrossProfitTotal(), 
      CommissionTotal = ordersummary.GetCommissionTotal(), 
      NetProfitTotal = ordersummary.GetNetProfitTotal(), 
     }; 
     return View(viewModel); 

Это заставляет меня все данные мне нужно в представлении, так что я могу работать с ним. Для меня это кажется излишним излишним, и я предполагаю, что он неэффективен? Если вы запишете, что я также занимаюсь сортировкой и поиском парм, у вас много дублирующего кода linq. Похоже, что я должен быть в состоянии сделать что-то, чтобы консолидировать данные, как это:

var orders = (from s in db.Orders 
       where s.UserId == uId 
       select s).ToList(); 

    decimal grossprofittotal = orders.Sum(s => s.Profit); 
    decimal commissiontotal = orders.Sum(s => s.Commission); 
    decimal netprofittotal = orders.Sum(s => s.Profit + s.Commission); 

, а затем обернуть эти четыре части данных (список заказов, а также три десятичные значения) красиво в массиве (или любой другой) и отправить их на контроллер/просмотр. В представлении мне нужно иметь возможность прокручивать список заказов. Неужели я здесь? Или, что такое стандартная процедура здесь с MVC? Благодарю.

ответ

1

Да, получение четырех одинаковых данных действительно неэффективно и совершенно ненужно. Вы можете очень хорошо получить его только один раз, а затем выполнить другие операции с данными, которые у вас есть.

Вы можете сохранить метод GetOrders так, как вам нравится, но это все данные, которые вам нужны для извлечения. Если вы извлекаете данные в контроллере или в конструкторе модели, это в основном вопрос вкуса. Лично я склонен ставить больше логики в модели, чем контроллер.

До тех пор, пока вы используете ToList, чтобы убедиться, что вы действительно извлекаете данные (или любой другой метод, который реализует результат в виде коллекции), вы можете рассчитать суммы из того, что у вас есть в памяти. (. Без этого, вы все равно будете делать четыре запроса к базе данных)

Вместо подведения прибыли и комиссионного от всех элементов, чтобы получить чистую сумму прибыли, вы можете просто вычислить его от других сумм:

decimal netprofittotal = grossprofittotal + netprofittotal; 
+0

Спасибо, имеет смысл и звучит так, как будто мне нужно вернуться к фундаментальным принципам, а не думать о MVC как о совершенно новом жестком способе делать вещи.К сожалению, мои фундаментальные особенности являются пятнистыми, но я могу, по крайней мере, смотреть за рамки коробки и вообще знать, где найти ответы. Я очень ценю помощь. – SumNone

1

LinqToEntities транслирует весь запрос в SQL. Если вы не хотите делать более одной транзакции, вы можете получить результат в переменную на .ToList(), запросив этот объект, выполните вычисление linqToObject в памяти.

Назад: сначала извлекает все заказы из базы данных.

var ordersInMemory = orders.ToList(); 
decimal grossprofittotal = ordersInMemory.Sum(s => s.Profit); 
decimal commissiontotal = ordersInMemory.Sum(s => s.Commission); 
decimal netprofittotal = grossprofittotal + commissiontotal ; 
+0

Метод «AsEnumerable» возвращает ссылку только как «IEnumerable », это не заставляет запрос, поэтому ваш код будет по-прежнему выполнять три вызова базы данных, а не один. http://msdn.microsoft.com/en-us/library/bb335435.aspx – Guffa

+0

Да, возвращает, но в этом случае объект использует стандартные методы методов по умолчанию, и он переходит в режим обработки. Я что-то не понимаю? http://msmvps.com/blogs/jon_skeet/archive/2011/01/14/reimplementing-linq-to-objects-part-36-asenumerable.aspx – speti43

+0

Это также доказывает мой предикат: http://stackoverflow.com/ Вопросы/2876616/return-ienumerablet-vs-iqueryablet – speti43