When working with Entity Framework Core and including multiple related entities, you may notice performance degradation or unexpected SQL behavior. One hidden gem to address this is the AsSplitQuery() method—a powerful tool that gives you greater control over how EF Core executes your queries.
In this article, we’ll explore:
- What
AsSplitQuery()does - Why it matters
- Real-world usage and benefits
- When not to use it
The Problem: Cartesian Explosion with Include
Let’s say you have a query like this:
var orders = context.Orders
.Include(o => o.OrderItems)
.Include(o => o.ShippingAddress)
.ToList();
By default, EF Core tries to optimize performance by generating a single SQL query that joins all related tables. This works fine in simple cases, but with many Include() calls, this approach can lead to:
- Redundant data loading
- Cartesian explosion: A bloated result set with repeating data
- Timeouts and degraded performance
The Solution: AsSplitQuery()
AsSplitQuery() tells EF Core to execute multiple SQL queries—one for the root entity and one for each included navigation.
var orders = context.Orders
.Include(o => o.OrderItems)
.Include(o => o.ShippingAddress)
.AsSplitQuery()
.ToList();
How It Works
Instead of one big join:
SELECT * FROM Orders
JOIN OrderItems ON ...
JOIN ShippingAddress ON ...
EF Core does:
SELECT * FROM Orders;
SELECT * FROM OrderItems WHERE OrderId IN (...);
SELECT * FROM ShippingAddress WHERE OrderId IN (...);
The data is then merged in memory by EF Core to maintain object relationships.
Real-Life Scenario
A developer noticed their application was slowing down when loading invoices with nested Include()s (invoice lines, customer, taxes, etc.).
The SQL Profiler showed a massive single query returning 10,000+ rows due to joins—even though they only had 500 invoices.
Switching to:
context.Invoices
.Include(i => i.Lines)
.Include(i => i.Customer)
.Include(i => i.Taxes)
.AsSplitQuery()
.ToList();
Resulted in:
- Faster execution
- Smaller result sets
- Cleaner query plans
When to Use AsSplitQuery
✅ Use When:
- You have multiple
Include()s - Data repetition is slowing things down
- Query plans are bloated
- You hit SQL Server row limits or timeouts
❌ Avoid When:
- You’re loading small, flat datasets
- You require exact transaction boundaries (split queries run separately)
- You’re concerned about multiple round-trips to the database
Bonus Tip: Set It Globally
You can configure EF Core to always use split queries:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("...", options => options.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery));
}
Final Thoughts
AsSplitQuery() is a simple yet powerful feature in EF Core that helps you avoid performance bottlenecks when working with complex object graphs. While it introduces additional round-trips, the trade-off is often worth it for cleaner, faster, and more scalable queries.
If your EF queries are slowing down due to heavy joins, try AsSplitQuery()—and let EF Core do the heavy lifting more efficiently.
