Bulk Insert
BulkInsert
lets you efficiently insert large amounts of data into your database using native bulk loaders under the hood. It works directly on any IDbConnection
and supports advanced options such as identity insert, batch size control, and column mapping.
Example
using System.Data.SqlClient;
using ETLBox.DbExtensions;
var connection = new SqlConnection("your-connection-string");
var data = Enumerable.Range(1, 10_000)
.Select(i => new Customer {
Id = i,
Name = $"Customer {i}",
City = $"City {i % 50}"
});
connection.BulkInsert(data.ToList());
public class Customer {
public int Id { get; set; }
public string Name { get; set; }
public string City { get; set; }
}
Method Signatures
IDbConnection BulkInsert<T>(
this IDbConnection connection,
IEnumerable<T> data
)
IDbConnection BulkInsert<T>(
this IDbConnection connection,
IEnumerable<T> data,
Action<BulkOptions<T>> options
)
Customization Options
You can configure the operation using the optional BulkOptions<T>
parameter:
var connection = new SqlConnection("your-connection-string");
var customers = Enumerable.Range(1, 4_999)
.Select(i => new Customer { Id = i, Name = $"Customer {i}", City = $"City {i % 50}" });
connection.BulkInsert(customers, options => {
options.BatchSize = 500;
options.TablePrefix = "dim";
options.ReadGeneratedValues = true;
options.OnProgress = progress => {
if (progress % 1000 == 0)
Console.WriteLine($"Inserted {progress} rows.");
};
});
For a complete list of available options, see the BulkOptions reference.
Reading Generated Values
If your database table includes columns with auto-generated values (e.g., identity columns or default constraints), you can instruct ETLBox to read these values back into your objects after the insert.
This is done by enabling the ReadGeneratedValues
option:
var connection = new SqlConnection("your-connection-string");
var customers = Enumerable.Range(0, 100)
.Select(i => new Customer { Name = $"Customer {i}", City = $"City {i % 10}" })
.ToList();
connection.BulkInsert(customers, options => {
options.ReadGeneratedValues = true;
});
// After the insert, customers[i].Id will contain the auto-generated ID
foreach (var c in customers.Take(3))
Console.WriteLine($"Inserted: {c.Id} - {c.Name}");
Requirements
- The property must be included in your class (e.g.,
Id
) - The target column in the database must be auto-generated (e.g., identity, serial)
- The feature must be supported by the ETLBox database provider you’re using
Inserting into Identity Columns
By default, most databases automatically generate values for identity (auto-increment) columns. If you want to explicitly insert values into those columns (e.g., during data migration or replication), you can enable identity insert using the AllowIdentityInsert
option:
var connection = new SqlConnection("your-connection-string");
var customers = Enumerable.Range(1, 100)
.Select(i => new Customer {
Id = i, // explicitly setting Id
Name = $"Imported Customer {i}",
City = $"City {i % 10}"
}).ToList();
connection.BulkInsert(customers, options => {
options.AllowIdentityInsert = true;
});
Ignoring Default Columns on Insert
Use IgnoreDefaultColumnsOnInsert = true
to skip inserting values into columns that have DEFAULT
constraints in the database. This allows the database to assign default values automatically.
connection.BulkInsert(customers, options => {
options.IgnoreDefaultColumnsOnInsert = true;
});
Table Naming Convention
By default, the table name is inferred from the class name. For example:
public class Customer { ... }
This maps to either Customer or Customers.
You can override the name using TableName
, or adjust it with TablePrefix
and TableSuffix
inside BulkOptions.
Example Code on GitHub
You can find both examples — basic usage and usage with options — in the official demo project on GitHub:
The demo is ready to run and shows how to configure the connection, create the table, and execute bulk operations with real data.