2015-04-24 5 views
5

Я пытаюсь понять, почему соединение в моем случае происходит быстрее, чем оператор, который использует свойство навигации. У меня два запроса.Entity framework performance join vs navigation property

Сначала с свойства навигации:

  var result = (from users in context.MetricBloodPreasure 
       orderby users.User.LastName, users.User.FirstName 
       select new 
       { 
        UserName = users.User.LastName + ", " + users.User.FirstName, 
        Date = users.DateOfValue, 
       }).ToList(); 

Generatet SQL:

SELECT 
    [Project1].[C1] AS [C1], 
    [Project1].[C2] AS [C2], 
    [Project1].[DateOfValue] AS [DateOfValue] 
    FROM (SELECT 
     [Extent1].[DateOfValue] AS [DateOfValue], 
     [Extent2].[FirstName] AS [FirstName], 
     [Extent2].[LastName] AS [LastName], 
     1 AS [C1], 
     CASE WHEN ([Extent2].[LastName] IS NULL) THEN N'' ELSE [Extent2].[LastName] END + N', ' + CASE WHEN ([Extent2].[FirstName] IS NULL) THEN N'' ELSE [Extent2].[FirstName] END AS [C2] 
     FROM [dbo].[MetricBloodPreasure] AS [Extent1] 
     INNER JOIN [dbo].[User] AS [Extent2] ON [Extent1].[UserId] = [Extent2].[Id] 
    ) AS [Project1] 
    ORDER BY [Project1].[LastName] ASC, [Project1].[FirstName] ASC 

Второй с присоединиться:

var result1 = (from u in context.User 
       orderby u.LastName, u.FirstName 
       join us in context.MetricBloodPreasure 
        on u.Id equals us.UserId into users 
       from s in users 
       select new 
       { 
        UserName = s.User.LastName + ", " + s.User.FirstName, 
        Date = s.DateOfValue, 
       }).ToList(); 

генерируемый SQL:

SELECT 
    1 AS [C1], 
    CASE WHEN ([Extent1].[LastName] IS NULL) THEN N'' ELSE [Extent1].[LastName] END + N', ' + CASE WHEN ([Extent1].[FirstName] IS NULL) THEN N'' ELSE [Extent1].[FirstName] END AS [C2], 
    [Extent2].[DateOfValue] AS [DateOfValue] 
    FROM [dbo].[User] AS [Extent1] 
    INNER JOIN [dbo].[MetricBloodPreasure] AS [Extent2] ON ([Extent1].[Id] = [Extent2].[UserId]) AND ([Extent2].[UserId] = [Extent1].[Id]) 

Перед запуском первого запроса позвоните var user = context.User.FirstOrDefault();, потому что я думаю, что открытое соединение с базой данных занимает некоторое время.

Результаты: Навигация свойство запроса: 00: 00: 00,6719646 Регистрация запроса: 00: 00: 00,4941169

Глядя на результаты, кажется, что Linq запросов, что использование присоединяется вместо навигационных свойств быстрее. Это правда, или я делаю что-то неправильно?

+0

Необходимо также очистить кеш от базы данных между запросами, чтобы получить правильные результаты при вызове ToList(). Отделите построение запроса от материализации и отметьте их. –

+0

OrderBy, похоже, не учитывается во втором запросе. Это может быть причиной разницы. Вы можете попробовать «... от s в порядке пользователей по u.LastName, u.FirstName ...» – jbl

ответ

2

Чтобы получить лучшее представление о том, что он делает, вы должны получить необработанный SQL, и вы можете сами проверить план выполнения.

Чтобы сделать это, вы можете использовать SQL Profiler, чтобы увидеть, что запрос является запуск, или вы можете войти в сам SQL запрос, делая что-то вроде этого, прежде чем запустить запрос:

context.Database.Log = s => System.Diagnostics.Debug.WriteLine(s); 

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

+0

Кроме того, добавление большего количества данных в базу данных является хорошей идеей, это должно подчеркнуть разницу (если существует) –

+0

оба запроса возвращены более чем 9000 строк ... и да, я использую журнал и запускаю запросы с новым экземпляром моего контекста базы данных. Регистрация еще быстрее. – puko

+0

Можете ли вы разместить SQL, который запускается в исходный вопрос? Кроме того, вы запустили SQL в SSMS и включили план выполнения, чтобы вы могли видеть, где различия? –