2014-10-27 2 views
0

Я использую EF 6.1.2-beta1 код первой в моей программе и имеют следующие модели в моем проекте (моя база данных создается самим EF, тоже):EF не дают ожидаемого SQL

enter image description here

public class Document 
{ 
    public int Id { get; set; } 
    public AppUser Creator { get; set; } 
    public AppUser Modifier { get; set; } 
} 
public class AppUser 
{ 
    public int Id { get; set; } 
    public string UserId { get; set; } 
    public Party Party { get; set; } 
}  
public class Party 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

I хотите написать запрос linq к объектам, чтобы найти Creator.Name и Modifier.Name из первых Document (для простоты я предположил, что хочу найти первый Document). Так что я написал следующий код:

var result = context.Documents.Select(d => 
      new{ 
        d.Id, 
        CreatorName = d.Creator.Party.Name, 
        ModifierName = d.Modifier.Party.Name, 
      }).FirstOrDefault(); 

EF генерировать следующие SQL для вышеупомянутого запроса:

SELECT TOP (1) 
[Extent1].[Id] AS [Id], 
[Extent3].[Name] AS [Name] 
FROM [dbo].[Documents] AS [Extent1] 
LEFT OUTER JOIN [dbo].[AppUser] AS [Extent2] 
      ON [Extent1].[Creator_Id] = [Extent2].[AppUserId] 
LEFT OUTER JOIN [dbo].[Parties] AS [Extent3] 
      ON [Extent2].[Party_Id] = [Extent3].[Id] 

Но, как вы видите, выше SQL только один присоединиться к Party таблице и поэтому получают только Creator.Name.

[Обновлено]

Вы можете получить мой тест исходный код проекта от here

Dos Кто-нибудь знает, где проблема?

ответ

1

Как только понижая к EF 6.1.1 решает эту проблему (генерируется SQL и результаты правильны) - Я думаю, что это ошибка в EF 6.1.2 бета.

Например, эта команда

var result = context.Documents.Select(d => 
    new 
    { 
     d.Id, 
     Creator = d.Creator, 
     CreatorParty = d.Creator.Party, 
     CreatorPartyName = d.Creator.Party.Name, 
     Modifier = d.Modifier, 
     ModifierParty = d.Modifier.Party, 
     ModifierPartyName = d.Modifier.Party.Name 
    }).FirstOrDefault(); 

Формирует SQL

SELECT TOP (1) 
    [Extent1].[Id] AS [Id], 
    [Extent2].[Id] AS [Id1], 
    [Extent2].[UserId] AS [UserId], 
    [Extent2].[Party_Id] AS [Party_Id], 
    [Extent3].[Id] AS [Id2], 
    [Extent3].[Name] AS [Name], 
    [Extent4].[Id] AS [Id3], 
    [Extent4].[UserId] AS [UserId1], 
    [Extent4].[Party_Id] AS [Party_Id1] 
    FROM [dbo].[Documents] AS [Extent1] 
    LEFT OUTER JOIN [dbo].[AppUsers] AS [Extent2] ON [Extent1].[Creator_Id] = [Extent2].[Id] 
    LEFT OUTER JOIN [dbo].[Parties] AS [Extent3] ON [Extent2].[Party_Id] = [Extent3].[Id] 
    LEFT OUTER JOIN [dbo].[AppUsers] AS [Extent4] ON [Extent1].[Modifier_Id] = [Extent4].[Id] 

Существует нет второго Parties присоединитесь из Extent4 (второй AppUsers)

[Update]

Благодаря Masoud (в комментариях) - эта ошибка в EF была исправлена ​​20 октября.

+0

Спасибо, как вы сказали, это была ошибка в 'EF 6.1.2 beta', которая описана в https://entityframework.codeplex.com/workitem/2548, она исправлена ​​в ночной сборке. обновите свой ответ. – Masoud

0

Этот запрос не соответствует анонимному типу, который вы даете, поэтому я думаю, что это просто выполняется, когда вы ссылаетесь на имя d.Creator.Party.Name, и вы перестаете регистрироваться там? Или выполняется несколько запросов?

Возможно, после?

var doc = (from d in context.Documents 
      .Include("Creator.Party").Include("Modifier.Party") 
      select new 
      { 
       Id = d.Id, 
       CreatorName = d.Creator.Party.Name, 
       ModifierName = d.Modifier.Party.Name 
      }).FirstOrDefault(); 
+0

Нет никакого другого сгенерированного 'SQL', и ваш предложенный запрос не будет совпадать с моим запросом. – Masoud

1

Попробуйте вместо этого несколько соединений.

var q = from d in context.Documents 
     join uCreator in context.AppUsers on d.Creator.Id equals uCreator.Id 
     join uModifier in context.AppUsers on d.Modifier.Id equals uModifier.Id 
     select new { 
      Id = d.Id, 
      Creator = uCreator.Party.Name, 
      Modifier = uModifier.Party.Name 
     };