Skip to content

Commit 843750a

Browse files
Copilotroji
andauthored
Document better SQL for to-one joins (EF Core 11 what's new) (#5288)
Document dotnet/efcore#37819 Co-authored-by: Shay Rojansky <roji@roji.org>
1 parent b636eb1 commit 843750a

1 file changed

Lines changed: 62 additions & 0 deletions

File tree

  • entity-framework/core/what-is-new/ef-core-11.0

entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,68 @@ For more information on inheritance mapping strategies, see [Inheritance](xref:c
7979

8080
## LINQ and SQL translation
8181

82+
<a name="linq-to-one-join-pruning"></a>
83+
84+
### Better SQL for to-one joins
85+
86+
EF Core 11 generates better SQL when querying with to-one (reference) navigation includes in two ways.
87+
88+
First, when using split queries (`AsSplitQuery()`), EF previously added unnecessary joins to reference navigations in the SQL generated for collection queries. For example, consider the following query:
89+
90+
```csharp
91+
var blogs = context.Blogs
92+
.Include(b => b.BlogType)
93+
.Include(b => b.Posts)
94+
.AsSplitQuery()
95+
.ToList();
96+
```
97+
98+
EF Core previously generated a split query for `Posts` that unnecessarily joined `BlogType`:
99+
100+
```sql
101+
-- Before EF Core 11
102+
SELECT [p].[Id], [p].[BlogId], [p].[Title], [b].[Id], [b0].[Id]
103+
FROM [Blogs] AS [b]
104+
INNER JOIN [BlogType] AS [b0] ON [b].[BlogTypeId] = [b0].[Id]
105+
INNER JOIN [Post] AS [p] ON [b].[Id] = [p].[BlogId]
106+
ORDER BY [b].[Id], [b0].[Id]
107+
```
108+
109+
In EF Core 11, the unneeded join is pruned:
110+
111+
```sql
112+
-- EF Core 11
113+
SELECT [p].[Id], [p].[BlogId], [p].[Title], [b].[Id]
114+
FROM [Blogs] AS [b]
115+
INNER JOIN [Post] AS [p] ON [b].[Id] = [p].[BlogId]
116+
ORDER BY [b].[Id]
117+
```
118+
119+
Second, EF no longer adds redundant keys from reference navigations to `ORDER BY` clauses. Because a reference navigation's key is functionally determined by the parent entity's key (via the foreign key), it does not need to appear separately. For example:
120+
121+
```csharp
122+
var blogs = context.Blogs
123+
.Include(b => b.Owner)
124+
.Include(b => b.Posts)
125+
.ToList();
126+
```
127+
128+
EF Core previously included `[p].[PersonId]` in the `ORDER BY`, even though `[b].[BlogId]` already uniquely identifies the row:
129+
130+
```sql
131+
-- Before EF Core 11
132+
ORDER BY [b].[BlogId], [p].[PersonId]
133+
```
134+
135+
In EF Core 11, the redundant column is omitted:
136+
137+
```sql
138+
-- EF Core 11
139+
ORDER BY [b].[BlogId]
140+
```
141+
142+
Both optimizations can have a significant positive impact on query performance, especially when multiple reference navigations are included.
143+
82144
<a name="linq-maxby-minby"></a>
83145

84146
### MaxBy and MinBy

0 commit comments

Comments
 (0)