When NOT to Use AsSplitQuery() in EF.core

posted 2 min read

When working with Entity Framework Core (EF Core), queries that involve multiple Include() statements can result in a single large query with multiple joins. This can cause performance issues due to data duplication and increased memory usage.

What is AsSplitQuery()?

AsSplitQuery() tells EF Core to fetch related data using separate SQL queries instead of one large join query. This helps optimize performance for complex queries.

Step 1: Setup Your Model

Let’s create a simple e-commerce scenario with Order, Customer, and OrderItem entities.

public class Order
{
    public int Id { get; set; }
    public string OrderNumber { get; set; }
    public Customer Customer { get; set; }
    public List<OrderItem> OrderItems { get; set; } = new();
}

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class OrderItem
{
    public int Id { get; set; }
    public string ProductName { get; set; }
    public int Quantity { get; set; }
}

Step 2: Configure the Database Context

We define our DbContext to include the necessary DbSet properties.

public class AppDbContext : DbContext
{
    public DbSet<Order> Orders { get; set; }
    public DbSet<Customer> Customers { get; set; }
    public DbSet<OrderItem> OrderItems { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlite("Data Source=app.db");
    }
}

Step 3: Query Without AsSplitQuery()

Let's say we want to fetch orders with their customers and order items.

**var orders = await _context.Orders
    .Include(o => o.Customer)
    .Include(o => o.OrderItems)
    .ToListAsync();**

What Happens Here?
EF Core generates a single SQL query with multiple JOIN operations.
If there are many orders and items, this can cause performance issues due to data duplication.

Step 4: Optimize with AsSplitQuery()

Now, let's improve performance by using AsSplitQuery().

var orders = await _context.Orders
    .Include(o => o.Customer)
    .Include(o => o.OrderItems)
    .AsSplitQuery() // Fetches data using multiple queries instead of joins
    .ToListAsync();

What Happens Now?

EF Core executes multiple separate SQL queries instead of a single large join.
Less memory is used since duplicate data is avoided.
Performance is improved when dealing with large datasets.

Step 5: Understanding the SQL Queries

Without AsSplitQuery()
EF Core runs one big SQL query:

SELECT o.*, c.*, oi.*
FROM Orders o
LEFT JOIN Customers c ON o.CustomerId = c.Id
LEFT JOIN OrderItems oi ON o.Id = oi.OrderId;

This may lead to repetitive customer data for each order item.

With AsSplitQuery()
EF Core runs separate queries:

SELECT * FROM Orders;
SELECT * FROM Customers WHERE Id IN (...);
SELECT * FROM OrderItems WHERE OrderId IN (...);

This reduces duplication and improves performance.

When to Use AsSplitQuery()

✅ Use AsSplitQuery() when:

You include multiple navigation properties (Include()).
You experience performance issues with large datasets.
You want to avoid data duplication.

❌ Avoid AsSplitQuery() when:

Your queries are already small and fast.
Your database round trips increase due to multiple queries.

Conclusion

Using AsSplitQuery() in EF Core can boost performance and reduce memory usage when working with complex queries. It’s a simple yet powerful optimization that can make your applications more efficient.

If you read this far, tweet to the author to show them you care. Tweet a Thanks
AsSplitQuery() is a total game-changer for EF Core performance!  No more bloated JOINs slowing things down. Maybe add a real-world benchmark comparison to show the speed boost?
The main benefit of using AsSplitQuery() is that it avoids Cartesian explosion. EF Core often creates a single query with multiple joins, and if the relationships contain many-to-many or one-to-many associations, this can lead to duplicated rows, causing performance issues.
Another advantage is that the query becomes more readable since each related entity is fetched separately rather than being combined into a complex join.
I'll keep this in mind and plan to create a simple project to benchmark the performance with and without AsSplitQuery().
Thanks for your comment!

More Posts

EF Core: Lazy Loading, Eager Loading, and Loading Data on Demand

Spyros - Mar 6

EF Core Global Query Filters: A Complete Guide

Spyros - Mar 2

How to use Builder design Pattern for test data generation in automation testing

Faisal khatri - Oct 14, 2024

Understanding the Observer Pattern in C# with IObservable and IObserver

Spyros - Mar 11

Suitable DB Choice in USSD Application

Moses Korir - Mar 12
chevron_left