Introduction
In this blog post, we'll explore how to perform bulk data insertion using Entity Framework in a C# application. Bulk insertion is a common requirement when dealing with large datasets, and it's essential to handle errors gracefully and efficiently. We'll cover the step-by-step process, including setting up the Entity Framework context, implementing retry logic for failed insertions, and handling errors effectively.
Step 1. Setting up the Entity Framework Context
First, let's create an Entity Framework context to interact with our database. Assume we have a simple DbContext class named AppDbContext with a DbSet for our entity type MyEntity.
public class AppDbContext : DbContext
{
public DbSet<MyEntity> MyEntities { get; set; }
// Constructor to configure database connection
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
}
Step 2. Implementing Bulk Data Insertion
Next, let's implement the method to perform bulk data insertion using Entity Framework. We'll use the AddRange method to add multiple entities to the context and then call SaveChanges to persist the changes to the database.
public class BulkDataProcessor
{
private readonly AppDbContext _dbContext;
public BulkDataProcessor(AppDbContext dbContext)
{
_dbContext = dbContext;
}
public void InsertBulkData(List<MyEntity> entities)
{
_dbContext.MyEntities.AddRange(entities);
_dbContext.SaveChanges();
}
}
Step 3. Implementing Retry Logic for Failed Insertions
To handle scenarios where bulk insertion fails due to transient errors (e.g., database connection issues), we'll implement retry logic. We'll retry the insertion operation a configurable number of times with a delay between retries.
public class BulkDataProcessor
{
// Previous code remains unchanged
public void InsertBulkDataWithRetry(List<MyEntity> entities, int maxRetries = 3, TimeSpan delayBetweenRetries = default)
{
int retries = 0;
bool success = false;
while (!success && retries < maxRetries)
{
try
{
InsertBulkData(entities);
success = true; // Mark insertion as successful
}
catch (DbUpdateException ex) when (IsTransientError(ex) && retries < maxRetries - 1)
{
// Transient error occurred, retry after delay
retries++;
if (delayBetweenRetries != default)
Thread.Sleep(delayBetweenRetries);
}
}
if (!success)
{
// Log or handle failed insertion after retries
Console.WriteLine($"Bulk data insertion failed after {maxRetries} retries.");
}
}
private bool IsTransientError(DbUpdateException ex)
{
// Check if the exception is due to a transient database error
// Implement logic to identify transient errors based on the exception type or message
return true; // Placeholder implementation
}
}
Let's integrate batch size handling into the bulk data insertion process using Entity Framework.
public class BulkDataProcessor
{
private readonly AppDbContext _dbContext;
private const int DefaultBatchSize = 1000; // Default batch size
public BulkDataProcessor(AppDbContext dbContext)
{
_dbContext = dbContext;
}
public void InsertBulkData(List<MyEntity> entities, int batchSize = DefaultBatchSize)
{
for (int i = 0; i < entities.Count; i += batchSize)
{
IEnumerable<MyEntity> batch = entities.Skip(i).Take(batchSize);
_dbContext.MyEntities.AddRange(batch);
_dbContext.SaveChanges();
}
}
public void InsertBulkDataWithRetry(List<MyEntity> entities, int maxRetries = 3, TimeSpan delayBetweenRetries = default, int batchSize = DefaultBatchSize)
{
int retries = 0;
bool success = false;
while (!success && retries < maxRetries)
{
try
{
InsertBulkData(entities, batchSize);
success = true; // Mark insertion as successful
}
catch (DbUpdateException ex) when (IsTransientError(ex) && retries < maxRetries - 1)
{
// Transient error occurred, retry after delay
retries++;
if (delayBetweenRetries != default)
Thread.Sleep(delayBetweenRetries);
}
}
if (!success)
{
// Log or handle failed insertion after retries
Console.WriteLine($"Bulk data insertion failed after {maxRetries} retries.");
}
}
private bool IsTransientError(DbUpdateException ex)
{
// Check if the exception is due to a transient database error
// Implement logic to identify transient errors based on the exception type or message
return true; // Placeholder implementation
}
}

Join the conversation! Your thoughts help the community grow.