开发者

Entity Framework - Navigation Properties Generating Extra JOINs

开发者 https://www.devze.com 2023-02-13 01:38 出处:网络
I have noticed some very ugly SQL generated by my Entity Framework queries. Even very simple queries are generating a lot of extra JOINs when I inspect the SQL.

I have noticed some very ugly SQL generated by my Entity Framework queries. Even very simple queries are generating a lot of extra JOINs when I inspect the SQL.

I created a simple model:

Orders

OrderID INT PK

OrderDate DATETIME

OrderHeaders

OrderID INT PK / FK

StatusID INT FK

StatusTypes

StatusID INT PK

Description NVARCHAR(50)

From the model, an order can have 0 or 1 Order Header. A header will have 1 Status Type.

I created the following query:

var orders = from o in db.Orders
             where o.OrderID == 1
             select new
             {
                 Order = o,
                 Status = o.OrderHeader.Status
             };

The SQL that was generated by this looked like:

SELECT 
    [Extent1].[OrderID] AS [OrderID], 
    [Extent1].[OrderDate] AS [OrderDate], 
    [Extent4].[StatusID] AS [StatusID], 
    [Extent4].[Description] AS [Description]
FROM    [dbo].[Orders] AS [Extent1]
LEFT OUTER JOIN [dbo].[OrderHeaders] AS [Extent2] ON [Extent1].[OrderID] = [Extent2].[OrderID]
LEFT OUTER JOIN [dbo].[OrderHeaders] AS [Extent3] ON [Extent2].[OrderID] = [Extent3].[OrderID]
LEFT OUTER JOIN [dbo].[StatusTypes] AS [Extent4] ON [Extent3].[OrderID] = [Extent4].[OrderID]
WHERE 1 = [Extent1].[OrderID]

As you can see, there are two unnecessary left joins in the query. Why is the SQL being generated like this? Am I querying this wrong? Am I not supposed to use the navigation properties in the query?

Do I need to resort to writing joins in the query itself so it doesn't generate extra joins for me? When I write the query using joins then the generated SQL doesn't have any extra JOINs, but the LINQ to Entities query is a lot uglier/more verbose:

var orders = from o in db.Orders
             join h in db.OrderHeaders on o.OrderID equals h.OrderID into orderHeader
             from h in orderHeader.DefaultIfEmpty()
             join s in db.StatusTypes on h.StatusID equals s.StatusID into statusType
             from s in statusType.Defau开发者_如何学编程ltIfEmpty()
             where o.OrderID == 1
             select new
             {
                 o,
                 s
             };

This generates SQL without extra joins but it is a lot uglier to look at from the C# side.

Does anybody know how to fix this?


The SQL generated by Entity Framework is OK in many cases, but there will certainly be cases where you will frown upon the resulting SQL.

First of all, do you really care? Does it cause a performance problem (probably not), or do you have a DBA behind your back who will shoot you if you put this in production? :-)

If you can live with it, don't bother. Otherwise yes, you will have to monitor the SQL generated for your queries and either adjust your linq queries, or resort to stored procedures or other ways of data access (or maybe switch ORMs...).

EDIT: this particular case is still obviously a bug in EF 4 of course...


Yep. I've noticed the same thing. Hopefully the superfluous join won't kill your performance too badly. Hopefully EF5 will clean that up.

See:

Too Many Left Outer Joins in Entity Framework 4?


For me it looks like a bug. If you simply run:

  var orders = from o in context.Orders
               where o.OrderId == 1
               select o.OrderHeader;

It will produce this:

SELECT 
[Extent1].[OrderId] AS [OrderId], 
[Extent3].[OrderId] AS [OrderId1], 
[Extent3].[Name] AS [Name], -- I added  this column to OrderHeaders
[Extent4].[StatusId] AS [StatusId]
FROM    [dbo].[Orders] AS [Extent1]
LEFT OUTER JOIN [dbo].[OrderHeaders] AS [Extent2] ON [Extent1].[OrderId] = [Extent2].[OrderId]
LEFT OUTER JOIN [dbo].[OrderHeaders] AS [Extent3] ON [Extent2].[OrderId] = [Extent3].[OrderId]
LEFT OUTER JOIN [dbo].[OrderHeaders] AS [Extent4] ON [Extent2].[OrderId] = [Extent4].[OrderId]
WHERE 1 = [Extent1].[OrderId]

Edit:

I want to know some explanation of this behavior so I reposted it on MSDN forum. I hope, we will get some answer.

Edit 2:

Check this answer. It is confirmed bug which will be solved in the next EF version.

0

精彩评论

暂无评论...
验证码 换一张
取 消