Improve Entity Framework Add Performance

Introduction

Problem

You overuse the Add method, and your application suffers from performance issues.

Learn – Why Entity Framework Add is Slow?

Example

using (var ctx = new CustomerContext())
{
foreach(var line in lines)
{
var customer = new Customer();
// …code…
ctx.Customers.Add(customer);
}
ctx.SaveChanges();
}

Stack Overflow – Related Questions


Solution

Using the Add method in a loop is usually a poor practice which impacts your application performance severely when poorly used.

  • USE AddRange over Add (Recommended)
  • SET AutoDetectChanges to false
  • SPLIT SaveChanges in multiple batches

Use AddRange over Add (Recommended)

When adding multiple entities, you should always use Entity Framework AddRange once with a list instead of calling multiple time the Add method.

Why?

  • The Add method DetectChanges after every records added.
  • The AddRange method DetectChanges after all records is added.

# Performance Comparisons

Operations 100 Entities 1,000 Entities 10,000 Entities
Add 15 ms 1,050 ms 105,000 ms
AddRange 1 ms 10 ms 120 ms

*: SaveChanges time not included

**: Entity with two relations


How?

1. CREATE a list

2. ADD entity to the list

3. USE AddRange with the list

4. SaveChanges

5. Done!

# Example

using (var ctx = new CustomerContext())
{
// 1. CREATE a list
List<Customer> customers = new List<Customer>();
foreach(var line in lines)
{
var customer = new Customer();
// …code…
// 2. ADD entity to the list
customers.Add(customer);
}
// 3. USE AddRange with the list
ctx.Customers.AddRange(customers);
// 4. SaveChanges
ctx.SaveChanges();
// 5. Done!
}

SET AutoDetectChanges to false

When adding multiple entities, if you cannot use AddRange, set Entity Framework AutoDetectChanges to false

Why

  • The Add method DetectChanges after every records added.

By disabling AutoDetectChanges, the DetectChanges method will only be invoked when you do it.

# Performance Comparisons

AutoDetectChanges 100 Entities 1,000 Entities 10,000 Entities
True (Default) 15 ms 1,050 ms 105,000 ms
False 1 ms 14 ms 180 ms

*: SaveChanges time not included

**: Entity with two relations


How

1. SET AutoDetectChangesEnabled = false

2. CALL DetectChanges before SaveChanges

3. SaveChanges

4. Done!

# Example

using (var ctx = new CustomerContext())
{
// 1. SET AutoDetectChangesEnabled = false
ctx.Configuration.AutoDetectChangesEnabled = false;
foreach(var line in lines)
{
var customer = new Customer();
// …code…
ctx.Customers.Add(customer);
}
// 2. CALL DetectChanges before SaveChanges
ctx.ChangeTracker.DetectChanges();
// 3. SaveChanges
ctx.SaveChanges();
// 4. Done!
}

SPLIT SaveChanges in multiple batches

This solution is not recommended.

When adding multiple entities, split entities with a batch size in multiple different contexts.

Why

More tracking entities your context contains, slower the DetectChanges method is! So by reducing the number of entities by context, you improve the performance.

# Performance Comparisons

Batch Size 100 Entities 1,000 Entities 10,000 Entities
unlimited 15 ms 1,050 ms 105,000 ms
10 3 ms 40 ms 350 ms
100 15 ms 125 ms 1,200 ms
1,000 15 ms 1,050 ms 10,200 ms

*: SaveChanges time not included

**: Entity with two relations


How

1. CREATE a batchSize variable

2. CALL SaveChanges before creating a new batch

3. CALL SaveChanges

4. Done!

# Example

// 1. CREATE a batchSize variable
int batchSize = 1000;
var ctx = new CustomerContext();
for (int i = 0; i < lines.Count; i++)
{
// 2. CALL SaveChanges before creating a new batch
if (i != 0 && i%batchSize == 0)
{
ctx.SaveChanges();
ctx = new CustomerContext();
}
var customer = new Customer();
// …code…
ctx.Customers.Add(customer);
}
// 3. CALL SaveChanges
ctx.SaveChanges();
// 4. Done!

Why Entity Framework Add is Slow?

In fact, the Add method is not slow at all. Adding an entity to a list cannot be that slow. It’s the DetectChanges method invoked inside the Add method which is insanely slow!

All solutions in this article involve either:

1. Invoking less often the DetectChanges methods

2. Reducing the number of items to improve DetectChanges performance

Learn – Why DetectChanges is slow