C# LINQ GroupJoin — Complete Guide
In this tutorial, you'll learn about C# LINQ GroupJoin. We cover key concepts, practical examples, and best practices.
You have customers and orders. You want each customer with their list of orders. A regular Join flattens the result — one row per order, repeating customer info. GroupJoin produces hierarchical results: each left element paired with a sequence of matching right elements.
Wrong
var query = customers.Join(
orders,
c => c.Id,
o => o.CustomerId,
(c, o) => $"{c.Name}: {o.Total}");
// Output: Flat list — each order is one row, customer name repeated
Output: "Alice: 50", "Alice: 30", "Bob: 20" — flat, not grouped.
Right
var query = customers.GroupJoin(
orders,
c => c.Id, // Left key selector
o => o.CustomerId, // Right key selector
(c, orderList) => new
{
Customer = c.Name,
OrderCount = orderList.Count(),
Total = orderList.Sum(o => o.Total)
});
Output: { Customer = "Alice", OrderCount = 2, Total = 80 }, { Customer = "Bob", OrderCount = 1, Total = 20 }.
Each result pairs one customer with all matching orders. orderList is an IEnumerable<Order>.
For the full join syntax in query form:
var query = from c in customers
join o in orders on c.Id equals o.CustomerId into orderGroup
select new { Customer = c.Name, Orders = orderGroup };
Prevention
- Use
GroupJoinfor parent-child relationships (one-to-many). - Use
GroupJoinwhen you need all children per parent. - Use
Join(flat) when you need a row per child. - Use
SelectManyafterGroupJoinif you need to flatten but keep parent data. - Use
DefaultIfEmptyafterGroupJoinfor left outer join behavior. - Use
GroupJoinwithIQueryablefor server-side hierarchical queries.
Common Mistakes with linq group join
- Using
returnto exit a function early instead of wrapping a pure value in the monad - Mixing let bindings with <- bindings in do notation, producing type errors
- Overlapping type class instances that cause GHC to reject the program with ambiguous dispatch errors
These mistakes appear frequently in real-world CSHARP code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
GroupJoin is used in DodaTech's reporting for customer-order summaries. For more LINQ, visit DodaTech.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro