2013-04-23 5 views
7

Мне нужно найти отдельные Кампании определенного пользователя. Пользователь имеет CodeRights, CodeRights содержит коды и коды, содержащие кампанию. Вот класс CodeRightEntity Framework выполняет слишком много запросов

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; } 
} 

Я хотел бы написать следующий SQL для этого:

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) 

Использование EF Я пишу этот код:

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

Сейчас на профилирование я вижу, что EF выполняет 2 SQL-запроса для каждого присутствующего CodeRight.

Я также вычислил время полного выполнения и EF занимает ~ 400 мс при использовании ADO.Net только ~ 8.

Теперь мой вопрос в том, что если EF действительно это медленное, или я делаю что-то неправильно?

редактирует

После двух блоков выполняется для каждого 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 

и

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

Можете ли вы показать код выполнения запроса? Этот вопрос (http://stackoverflow.com/questions/8473705/linq-to-entities-distinct-on-one-column) указывает, что EF должен генерировать правильный запрос с использованием 'DISTINCT' –

+4

Компромисс для ORM's что они «болтливые». В большинстве случаев производительность «достаточно хороша». Но они болтливые. Но вы тратите меньше времени на создание пользовательского кода ORM. Выберите яд. Можно подумать, что вы можете увидеть, как EF выдает запрос и видит ли индекс, который стоит добавить. – granadaCoder

+0

@ w.brian См. Правки. –

ответ

10

Вы должны провести время, глядя на Fetch Plans for Entity Framework. Для того, чтобы EF выполнил соединение, вам нужно будет использовать ключевое слово Include.

Придется быть частью вашего первоначального запроса, когда вы получите ваш user объект:

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

CodeRights - это набор типов CodeRight, поэтому он не может «включать». –

+1

«Include» должен быть частью запроса, который возвращает пользователя, например «var user = context.Users.Include (« CodeRights.Code »). Включить (« CodeRights.Campaign »). FirstOrDefault (u = > u.Id == id); ' –

+0

@ApurvGupta Обновлено. – mattytommo

Смежные вопросы