简体   繁体   中英

Entity Framework using Sub Select not INNER JOIN

I have the below classes such as

public class Team
{
    [Key]
    public virtual Int32 TeamId { get; set; }
    [Required]
    public virtual String Name { get; set; }
    public virtual String Description { get; set; }
    public virtual ICollection<TeamFeed> TeamFeeds { get; set; }
}

public class TeamFeed
{       
    public Int32 TeamFeedId { get; set; }
    [Required]
    public Int32 TeamId { get; set; }
    public virtual bool IsEnabled { get; set; }
    public virtual Team Team { get; set; }
}

I have LazyLoadingEnabled = false and ProxyCreationEnabled = false

When I do

var team = db.Teams.Where(x => x.TeamId == 1).Include(x=>x.TeamFeeds);

The SQL generated by EF looks like:

SELECT 
[Project1].[TeamId] AS [TeamId], 
[Project1].[Name] AS [Name], 
[Project1].[Description] AS [Description], 
[Project1].[C1] AS [C1], 
[Project1].[TeamFeedId] AS [TeamFeedId], 
[Project1].[TeamId1] AS [TeamId1], 
[Project1].[IsEnabled] AS [IsEnabled], 
FROM ( SELECT 
    [Extent1].[TeamId] AS [TeamId], 
    [Extent1].[Name] AS [Name], 
    [Extent1].[Description] AS [Description],  
    [Extent2].[TeamFeedId] AS [TeamFeedId], 
    [Extent2].[TeamId] AS [TeamId1], 
    [Extent2].[IsEnabled] AS [IsEnabled],  
    CASE WHEN ([Extent2].[TeamFeedId] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
    FROM  [dbo].[Teams] AS [Extent1]
    LEFT OUTER JOIN [dbo].[TeamFeeds] AS [Extent2] ON [Extent1].[TeamId] = [Extent2].[TeamId]
    WHERE 1 = [Extent1].[TeamId]
)  AS [Project1]
ORDER BY [Project1].[TeamId] ASC, [Project1].[C1] ASC

I don't understand why it hasn't used SQL that I would use and created a long winded SQL statement.

SELECT 
* --use all just for clarity in the example
FROM TEAMS T

INNER JOIN TEAMFEEDS TF
ON T.TEAMID = TF.TEAMID

ORDER BY 
T.TEAMID

I'm new to EF so it may be I'm not be understanding something.

Thanks

First of all, your query using INNER JOIN won't return anything, when Team with TeamID = 1 has no feeds. LEFT JOIN has to be used here, and that's what EF did in ineer SELECT :

SELECT 
    *
    FROM  [dbo].[Teams] AS [Extent1]
    LEFT OUTER JOIN [dbo].[TeamFeeds] AS [Extent2] ON [Extent1].[TeamId] = [Extent2].[TeamId]
    WHERE 1 = [Extent1].[TeamId]

Following scary line is just to let EF know, if left site of the JOIN was specified - it returns 0 if Team has no Feeds and 1 if at lease one Feed was found.

CASE WHEN ([Extent2].[TeamFeedId] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]

And outer SELECT statement just maps DataBase columns names to EF model properties names and does ORDER BY .

Hope it's enough of explenation why EF generated such a long winded SQL statement . Or rather why this statement only looks scary, but really is not much more then your simple SELECT * FROM Teams JOIN Feeds .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM