2014-10-22 3 views
1

У меня есть набор связанных объектов. Я использую LINQ к группе коллекцию типа объекта по свойству на связанной сущности, а затем делает расчет суммы на собственность другого соответствующего лица:Оптимизация Linq для объектов

Vehicles.GroupBy(v => v.Mechanics.Engine.Size) 
     .Select(g => g.Sum(s => s.Passengers.Count)); 

Я пытаюсь сделать столько, сколько возможно через linq для объектов, поскольку в db имеется большое количество записей. Тем не менее, сгенерированный sql включает в себя 9 операторов select и внешнее применение, которое занимает более чем в 5 раз больше, чем выполнение, как запись упрощенного кода sql для достижения того же в одном предложении select.

Как улучшить сгенерированный sql?

+1

Прежде всего, я впечатлен тем, что вы профилировали sql, сгенерированный так много не –

+1

Вы уверены, что это единственный код, который формирует запрос? Вы должны включить сгенерированный sql и упрощенную версию. У вас также может быть проблема [N + 1] (http://stackoverflow.com/questions/97197/what-is-the-n1-selects-issue). Было бы неплохо увидеть ваши определения моделей. Я создал простой запрос, очень похожий на ваш, что привело к 1 довольно простой sql –

ответ

0

Вы на самом деле подсчета количества пассажиров в размере двигателя. Таким образом, свойства навигации позволяет, вы также можете сделать:

Passengers.GroupBy(p => p.Vehicle.Mechanics.Engine.Size) 
      .Select(g => g.Count()) 

Это, вероятно, генерировать более присоединяется и менее подзапросов. И только один агрегирующий оператор вместо двух в исходном запросе, из которых один (Count) повторяется для каждого размера.

0

Возможно попробовать запрос так:

Vehicles 
    .Select(x => new 
    { 
     EngineSize = x.Mechanics.Engine.Size, 
     PassengersCount = xs.Passengers.Count, 
    }) 
    .ToArray() 
    .GroupBy(v => v.EngineSize) 
    .Select(g => g.Sum(s => s.PassengersCount)); 

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

0

Вы также могли бы рассмотреть гибридный подход, при котором вы обходите поколение запроса LINQ еще использовать EF проецировать результаты в сильные тип, как это:

public List<Vechicles> GetVehcileInformation(string VehicleType){ 
    var QueryString = Resources.Queries.AllVehicles; 
    var parms = new List<SqlParameters>(); 
    parms.Add(new SqlParameter("VehicleType", VehicleType); 
    try{ 

     using (var db = new MyEntities()){ 
     var stuff= db.SqlQuery<Vehicles>(QueryString, parms.ToArray()); 
     return stuff.ToList(); 
     } 

    }catch(exception iox){Log.ErrorMessage(iox);} 

} 

Идея о том, что группа по делаются на уровне БД, который дает вы больше контролируете, чем в LINQ. Вы получаете скорость прямых запросов SQL, но возвращаете строго типизированные результаты! Сама строка запроса хранится в файле ресурсов в виде строки с держателями Параметр место, как это:

Select * from Table Where FieldName = @VehicleType... 
Смежные вопросы