Оптимизация Lambda Linq для SQL-запроса с помощью OrderBy - PullRequest
0 голосов
/ 02 июля 2010

У меня есть следующее лямбда-выражение:

IEnumerable<Order> query
       = _ordersRepository.GetAllByFilter(
            o => 
                o.OrderStatus.OrderByDescending(os => os.Status.Date).First()
                    .Status.StatusType.DisplayName != "Completed"
                ||   
                o.OrderStatus.OrderByDescending(os => os.Status.Date).First()
                    .Status.Date > sinceDate
         ).OrderBy(o => o.DueDate);

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

1) Достаточно ли умен оптимизатор запросов, чтобы эффективно справиться с этим?

2) Если нет, как я могу переписать это выражение только один раз, но с использованием синтаксиса лямбды ?

Это связано с предыдущим вопросом , который объясняет запрос более подробно, если приведенный выше код неясен.

Ответы [ 2 ]

2 голосов
/ 02 июля 2010

1) Достаточно ли умен оптимизатор запросов для эффективного решения этой проблемы?

Вы можете получить SQL для этого запроса (один из способов - использовать профилировщик SQL), а затем спросите SQL Studio о плане выполнения.Если вы не сделаете этого, нет способа узнать, что думает оптимизатор.Я предполагаю, что ответ «нет».

2) Если нет, то как я могу переписать это выражение только один раз, но с использованием синтаксиса лямбды?

Вот так:

IEnumerable<Order> query = _ordersRepository.GetAllByFilter( o =>
  o.OrderStatus
    .OrderByDescending(os => os.Status.Date)
    .Take(1)
    .Any(os => os.Status.StatusType.DisplayName != "Completed"
      || os.Status.Date > sinceDate)
})
.OrderBy(o => o.DueDate); 
0 голосов
/ 02 июля 2010

Относительно вашего первого замечания: вы можете увидеть SQL, сгенерированный, подписавшись на выходные данные объекта DatabaseContext. Обычно это свойство, называемое Log.

Что касается оптимизации вашего запроса, попробуйте следующее (я не проверял его, поэтому я не знаю, будет ли он работать)

IEnumerable<Order> query
   = _ordersRepository.GetAllByFilter(
        o =>
            o.OrderStatus.Max(os => os.Status.Date).Any(os =>
                os.Status.StatusType.DisplayName != "Completed"
                || os.Status.Date > sinceDate)
     ).OrderBy(o => o.DueDate);

Надеемся, что этот подзапрос будет выполнен только один раз, а также будет выполнен максимум, а не порядок с вершиной 1.

...