Почему Entity Framework не добавляет куда в SQL, сгенерированный при использовании SingleOrDefault?

Я использую Entity Framework CTP 5 с «только кодом» (с SQL Server 2008). У меня есть сущность, возвращенная из DbContext, из которой я затем получаю доступ к дочерней коллекции и выбираю из нее один элемент. Вот мой оператор LINQ:

Question currentQuestion = currentTopic.Questions.SingleOrDefault(x => x.IsCurrent);

Это производит следующий SQL:

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[CreatedAt] AS [CreatedAt], 
[Extent1].[IsCurrent] AS [IsCurrent], 
[Extent1].[Xml] AS [Xml], 
[Extent1].[TopicId] AS [TopicId]
FROM [dbo].[Questions] AS [Extent1]
WHERE [Extent1].[SessionId] = 24

Мое ограничение «IsCurrent» вообще не упоминается. IsCurrent — это битовое поле в моей базе данных.

Кто-нибудь может объяснить, почему это так? Это вызывает огромный удар по производительности.


person dommer    schedule 01.03.2011    source источник
comment
не уверен... x => x.IsCurrent == true   -  person rene    schedule 01.03.2011


Ответы (2)


Это предусмотрено во всех реализациях EF. Коллекция вопросов предоставляет IEnumerable<Question>, а не IQueryable<Question>. При доступе к свойству «Вопросы» запускается отложенная загрузка, и загружаются все связанные вопросы. Затем вы вызываете SingleOrDefault для загруженной коллекции.

Если вам нужен только один вопрос, запустите этот запрос:

var question = context.Questions
                 .SingleOrDefault(q => q.Session.Id == sessionId && q.IsCurrent);
person Ladislav Mrnka    schedule 01.03.2011

Я думаю, потому что дочерняя коллекция (currentTopic.Questions) лениво загружается полностью, а затем для вашей коллекции вызывается версия LINQ to Object SingleOrDefault, а не версия LINQ to Entities.

Опубликованный вами оператор SQL содержит WHERE [Extent1].[SessionId] = 24. Это показывает, что он загружает все вопросы для вашей текущей темы.

person Kristof Claes    schedule 01.03.2011