Sitemap
NorbertMarkiel

NorbertMarkiel

Why Is BULK INSERT So Much Faster Than AddRangeAsync?

2 min readJul 1, 2026

--

Press enter or click to view image in full size

If you’ve ever imported thousands of records into SQL Server, you’ve probably noticed that BULK INSERT or SqlBulkCopy can be 10x to even 50x faster than using Entity Framework.

Many developers assume that AddRangeAsync() performs a bulk insert. It doesn't. Consider the following code:

public async Task InsertBulkAsync(IEnumerable<TEntity> entities, CancellationToken token = default)
{
await context.AddRangeAsync(entities, token);
}

At first glance, it looks like we’re inserting a collection of entities in a single operation. In reality, AddRangeAsync() only attaches those entities to EF Core's ChangeTracker.

The actual database operation happens when SaveChangesAsync() is called.

await context.AddRangeAsync(users);
await context.SaveChangesAsync();

Even though you added a collection, EF Core still generates individual INSERT statements for each entity (or batches them internally, depending on the provider and configuration). Each row must still go through the normal SQL Server pipeline:

  • validation of constraints,
  • index updates,
  • transaction logging,
  • execution of an INSERT statement.

This introduces a significant amount of overhead when importing large datasets.

How BULK INSERT Is Different

BULK INSERT follows a completely different execution path inside SQL Server.

Get NorbertMarkiel’s stories in your inbox

Join Medium for free to get updates from this writer.

Instead of executing thousands of INSERT statements, SQL Server streams the data directly into the target table using an optimized bulk-loading engine.

This reduces overhead by:

  • minimizing network round trips,
  • reducing transaction log writes (when minimal logging is available),
  • processing data in large batches,
  • avoiding repeated SQL parsing and execution.

That’s why importing one million rows with BULK INSERT often finishes in seconds, while an EF Core approach may take several minutes.

Does This Mean You Should Never Use AddRangeAsync?

Not at all.

AddRangeAsync() is still the right choice for most business operations where you're inserting dozens or even a few thousand entities as part of your application's domain logic.

However, if you’re importing CSV files, migrating historical data, synchronizing external systems, or processing millions of records, specialized tools like BULK INSERT or SqlBulkCopy are the better choice.

The Takeaway

AddRangeAsync() is an ORM convenience method—not a bulk-loading mechanism.

If your application needs to move large volumes of data, the fastest solution isn’t optimizing Entity Framework. It’s bypassing it and using SQL Server’s native bulk-loading capabilities.

--

--