Search code examples
sqlentity-framework-4linq-to-entitiescode-firstef4-code-only

Why doesn't Entity Framework add a "where" to the SQL generated when SingleOrDefault is used?


I'm using Entity Framework CTP 5 with "code only" (with SQL Server 2008). I have an entity returned from a DbContext that I then access a child collection from, and select one item from it. Here's my LINQ statement:

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

This produces the following 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

My "IsCurrent" restriction isn't referenced at all. IsCurrent is a bit field in my database.

Can anyone explain why this is? It's causing a huge performance hit.


Solution

  • That is by design in all EF implementations. Questions collection exposes IEnumerable<Question> not IQueryable<Question>. When you access Questions property lazy loading is triggered and all related questions are loaded. Then you call SingleOrDefault on loaded collection.

    If you want just single question run this query instead:

    var question = context.Questions
                     .SingleOrDefault(q => q.Session.Id == sessionId && q.IsCurrent);