Стандартные операторы запроса с LINQ - Статистические выражения, иерархии и проекции

ОГЛАВЛЕНИЕ

Статистические выражения, иерархии и проекции

Применение статистических операторов, таких как Sum, в методе «LINQ — сущности» может значительно упростить запрос. Например, следующий фрагмент кода позволяет получить последовательность заказов на общую сумму более 10 000 долларов США:

using (Entities entities = new Entities())
{
  var query = from o in entities.Orders
  where o.OrderDetails.Sum(
  od => od.UnitPrice * od.Quantity) >= 10000
  select o;
  foreach (Orders order in query)
  Console.WriteLine(order.OrderID);
}

Поскольку LINQ позволяет выполнять запросы по иерархическим коллекциям сущностей, стандартные операторы запросов тоже могут применяться ко вложенным последовательностям. Это может пригодиться в том случае, если нужно выполнять вычисления с производными данными или опрашивать их. Производные данные существуют только в форме набора базовых данных. В качестве примера можно привести заказы, в данных которых указана только цена и количество. Общая сумма заказа нигде не указывается. Применяя оператор Sum к запросу LINQ, можно, к примеру, получить список клиентов, потративших более 20 000 долларов на заказы:

using (Entities entities = new Entities())
{
  var query = from c in entities.Customers
  where c.Orders.Sum(
  o => o.OrderDetails.Sum(
  od => od.UnitPrice * od.Quantity)) >= 25000
  select c;
  foreach (Customers customer in query)
  Console.WriteLine(customer.CompanyName);

Этот пример показывает порядок применения стандартных операторов на различных уровнях запроса LINQ. В конечном итоге запрос возвращает последовательность сущностей Customer, но для этого нужно сначала проникнуть в данные, составляющие заказ, и получить сведения, необходимые для расчета стоимости каждой позиции, просуммировать позиции в каждом заказе, а потом сложить итоговые суммы по заказам каждого отдельно взятого клиента.

Оператор Count — еще один пример стандартного статистического оператора. Он позволяет, к примеру, узнать количество клиентов, потративших более 25 000 долларов:

using (Entities entities = new Entities())
{
  var query = (from c in entities.Customers
  where c.Orders.Sum(
  o => o.OrderDetails.Sum(
  od => od.UnitPrice * od.Quantity)) >= 25000
  select c).Count();
  Console.WriteLine(query);

Оператор Max можно использовать для того, чтобы определить лучшего клиента компании. Следующий фрагмент кода возвращает сумму, которую потратил самый расточительный клиент. Здесь используется сочетание статистических операторов Sum и Max на различных уровнях иерархии:

using (Entities entities = new Entities())
{
  var query = (from c in entities.Customers
  select new
  {
  c.CustomerID, 
  Total = c.Orders.Sum(
  o => o.OrderDetails.Sum(od => od.UnitPrice))
  }).Max(c2 => c2.Total);
  Console.WriteLine(query);