2013-04-23 16 views
7

Potrzebuję znaleźć różne kampanie danego użytkownika. Użytkownik ma CodeRights, CodeRights zawiera Codes and Codes include Campaign. Oto klasa CodeRightEntity Framework wykonuje zbyt wiele zapytań.

public class SmartCodeRight 
{ 
     [Key, Column(Order = 1)] 
     public long UserId { get; set; } 
     public virtual User User { get; set; } 

     [Key, Column(Order = 2)] 
     public long CodeId { get; set; } 
     public virtual SmartCode Code { get; set; } 

     public CodeRight CodeRight { get; set; } 
} 

chciałbym napisać następujący SQL dla tego:

SELECT * 
FROM campaigns 
WHERE campaignid IN (SELECT DISTINCT campaignid 
        FROM smartcodes t1 
        INNER JOIN smartcoderights t2 ON t1.codeId = t2.codeId 
        WHERE t2.userid = @userId) 

Korzystanie EF piszę ten kod:

var v = user.CodeRights.Select(r => r.Code.Campaign).Distinct().ToList(); 

Teraz na profilowaniu widzę, że EF wykonuje 2 zapytania SQL dla każdego obecnego CodeRight.

Obliczyłem również czas całej realizacji i EF trwa ~ 400 ms podczas korzystania z ADO.Net to tylko ~ 8.

Teraz moje pytanie jest takie, że jeśli EF jest naprawdę tak wolno lub robię coś nie tak?

Edits

następujące dwa bloki są wykonywane dla każdego CodeRight

exec sp_executesql N'SELECT 
[Extent1].[CodeId] AS [CodeId], 
[Extent1].[CodeTitle] AS [CodeTitle], 
[Extent1].[CodeContent] AS [CodeContent], 
[Extent1].[CreatedOn] AS [CreatedOn], 
[Extent1].[IsActive] AS [IsActive], 
[Extent1].[Deleted] AS [Deleted], 
[Extent1].[OwnerId] AS [OwnerId], 
[Extent1].[Tags] AS [Tags], 
[Extent1].[CampaignId] AS [CampaignId] 
FROM [dbo].[SmartCodes] AS [Extent1] 
WHERE [Extent1].[CodeId] = @EntityKeyValue1',N'@EntityKeyValue1 bigint',@EntityKeyValue1=24 
go 

i

exec sp_executesql N'SELECT 
[Extent1].[CampaignId] AS [CampaignId], 
[Extent1].[Name] AS [Name], 
[Extent1].[Description] AS [Description], 
[Extent1].[AdminId] AS [AdminId] 
FROM [dbo].[Campaigns] AS [Extent1] 
WHERE [Extent1].[CampaignId] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=12 
go 
+0

można wyświetlić kod wykonujący zapytanie? To pytanie (http://stackoverflow.com/questions/8473705/linq-to-entities-distinct-on-one-column) wskazuje, że EF powinno generować odpowiednie zapytanie za pomocą 'DISTINCT' –

+4

. Kompromis dla ORM jest że są "rozmowni". Przez większość czasu występ jest "wystarczająco dobry". Ale są rozmowni. Ale spędzasz mniej czasu na pisaniu niestandardowego kodu ORM. Wybierz truciznę. Można pomyśleć, że EF wydaje zapytanie i czy istnieje indeks, który warto dodać. – granadaCoder

+0

@ w.brian Proszę zobaczyć zmiany. –

Odpowiedz

10

powinien spędzić czas patrząc na Fetch Plans for Entity Framework. Aby EF mógł wykonać łączenie, musisz użyć słowa kluczowego Include.

To będzie musiał być częścią wstępnego zapytania, gdy masz swoje user obiektu:

var user = context.Users 
    .Include("CodeRights.Code") 
    .Include("CodeRights.Campaign") 
    .FirstOrD‌​efault(u => u.Id == id); 
+0

CodeRights jest zbiorem typu CodeRight, więc nie może mieć tam "Uwzględnij". –

+1

"Uwzględnij" musi być częścią kwerendy, która zwraca użytkownika, coś jak 'var user = context.Users.Include (" CodeRights.Code "). Włącz (" CodeRights.Campaign "). FirstOrDefault (u = > u.Id == id); ' –

+0

@ApurvGupta Zaktualizowano. – mattytommo

Powiązane problemy