Entity Framework Core 10: Finally, Clean LEFT and RIGHT JOINs in LINQ
After more than two decades of writing workarounds for outer joins in LINQ, .NET developers finally have something to celebrate. Entity Framework Core 10, released in November 2025 as part of the .NET 10 platform, introduces the LeftJoin and RightJoin operators, a long-awaited feature that transforms how we write database queries.
The Problem We’ve Been Living With
If you’ve worked with Entity Framework for any length of time, you’ve likely encountered the awkward dance required to perform a LEFT JOIN. While SQL makes this straightforward with its LEFT JOIN syntax, LINQ has historically required a verbose combination of GroupJoin, SelectMany, and DefaultIfEmpty, a pattern that’s neither intuitive nor maintainable.
Here’s what we had to write before EF Core 10:
var query = context.Students
.GroupJoin(
context.Departments,
s => s.DepartmentID,
d => d.ID,
(s, deptGroup) => new { s, deptGroup }
)
.SelectMany(
x => x.deptGroup.DefaultIfEmpty(),
(x, dept) => new
{
StudentName = x.s.FirstName + " " + x.s.LastName,
DepartmentName = dept != null ? dept.Name : "[NONE]"
}
);
This code works, but it obscures intent. When reading it, you have to mentally translate the pattern back
into what you actually want: a simple left join.
The Solution: LeftJoin and RightJoin
EF Core 10 adds first-class support for the new .NET 10 LINQ operators LeftJoin and RightJoin, eliminating the need for complex workarounds. Now, the same query becomes beautifully simple:
var query = context.Students
.LeftJoin(
context.Departments,
student => student.DepartmentID,
dept => dept.ID,
(student, dept) => new
{
StudentName = student.FirstName + " " + student.LastName,
DepartmentName = dept?.Name ?? "[NONE]";
}
);
The code now reads exactly like what it does. When EF Core translates this to SQL, it generates a proper LEFT JOIN statement, preserving all records from the left side (Students) while matching available records from the right side (Departments).
Why This Matters for Real Applications
Consider a common scenario: building a customer dashboard that displays all customers, including those who haven’t placed any orders yet. With the old approach, developers had two equally undesirable options:
- Write the cumbersome GroupJoin pattern, making the codebase harder to understand and maintain
- Execute separate queries and combine the results in memory, sacrificing performance
The new LeftJoin and RightJoin methods mean the code finally matches the mental model. You can now express your intent clearly while letting EF Core handle the efficient translation to SQL.
Practical Examples
Customer Orders Dashboard
var customerOrders = context.Customers
.LeftJoin(
context.Orders,
customer => customer.Id,
order => order.CustomerId,
(customer, order) => new
{
CustomerName = customer.Name,
OrderId = order?.Id,
OrderDate = order?.OrderDate
}
);
This query ensures all customers appear in the results, with order information when available and null values when a customer has no orders.
Multi-Column Joins
For relationships based on composite keys, the syntax remains clean:
var query = context.Table1
.LeftJoin(
context.Table2,
outer => new { outer.Col1, outer.Col2 },
inner => new { inner.Col1, inner.Col2 },
(outer, inner) => new
{
// Select required columns
}
);
Right Joins
Similarly, RightJoin provides the inverse operation, keeping all records from the right side:
var departmentEmployees = context.Departments
.RightJoin(
context.Employees,
dept => dept.ID,
emp => emp.DepartmentID,
(dept, emp) => new
{
EmployeeId = emp.ID,
EmployeeName = emp.Name,
DepartmentName = dept?.Name
}
);
Important Considerations
While this feature is a significant improvement, there are a few things to keep in mind:
Method Syntax Only: Currently, only method syntax (.LeftJoin()) is supported. Query expression syntax (from … join … on) doesn’t yet support these operators.
Null Handling: Since outer joins can produce null values on the joined side, you’ll need to handle potential nulls explicitly using the null-conditional operator (?.) or null-coalescing operator (??).
Database Support: These operators work with relational database providers like SQL Server, PostgreSQL, and Oracle that support SQL JOIN operations.
.NET 10 Required: This feature requires upgrading to .NET 10 it won’t work on earlier .NET versions or .NET Framework.
Backward Compatibility: The traditional Group Join approach still works, ensuring existing code continues to function while you migrate to the new syntax.
The Bigger Picture
This addition might seem small, just two new methods, but it represents a meaningful improvement in developer experience. For years, the mismatch between SQL’s straightforward JOIN syntax and LINQ’s GroupJoin pattern has been a source of frustration. Developers would sometimes avoid proper outer joins altogether, leading to incorrect results or inefficient queries.
The LeftJoin and RightJoin methods are small additions but huge wins for productivity. They align LINQ more closely with SQL capabilities, making database queries more intuitive and maintainable.
Getting Started
To use these features, ensure you have:
- .NET 10 SDK installed
- Entity Framework Core 10.0 or later
- A relational database provider (SQL Server, PostgreSQL, Oracle, etc.)
Update your project’s target framework and EF Core packages, and you’re ready to start simplifying your queries.
Conclusion
Entity Framework Core 10’s LeftJoin and RightJoin operators eliminate a long-standing pain point in LINQ development. No more wrestling with GroupJoin patterns or sacrificing code clarity for functionality. The queries you write now directly express your intent, making your codebase more readable and maintainable.
If you’re working with relational data in .NET 10, this is one feature you’ll want to adopt immediately. Your future self and your teammates will thank you for writing code that actually says what it means.