Keep the engine. Drop the DataTable.
Beyond SqlBulkCopy
SqlBulkCopy is the right insert path on SQL Server. It is not an ETL API. ETLBox uses it under the hood, then covers update, merge, and other databases.
SqlBulkCopy is not slow. On SQL Server it is the native bulk insert, and if you already maintain a DataTable plus column maps, it stays a valid choice. In the documented benchmark it was a few milliseconds faster than ETLBox BulkInsert because there is no object mapping.
Reach past it when the next job is an update, a merge, a POCO, or PostgreSQL.
The class you already know
using var bulk = new SqlBulkCopy(connection) {
DestinationTableName = "Customer"
};
bulk.ColumnMappings.Add("Id", "Id");
bulk.ColumnMappings.Add("Name", "Name");
bulk.WriteToServer(table);POCOs, same bulk path — and not only insert
var dest = new DbDestination<Customer>(conn, "Customer");
source.LinkTo(dest);
Network.Execute(source);On SQL Server, DbDestination and BulkInsert use SqlBulkCopy. You keep your objects. Update, delete, and merge are the same family: DbMerge, or BulkUpdate / BulkDelete / BulkMerge on IDbConnection if you are not building a data flow.
What SqlBulkCopy does not do
The class is insert-only and SQL Server only. That is not a criticism. It is the surface Microsoft shipped. ETLBox does not pretend to beat raw SqlBulkCopy on a SQL Server insert. It wraps that path and covers the rest.
Bulk, then the rest of ETL
- SqlBulkCopy on SQL Server inserts
- POCOs — no
DataTable -
DbMergefor upsert and sync - Every database we ship a connector for — and files when you switch
- Same engine in a data flow or on
IDbConnection
One operation, one database
- Insert only
- SQL Server only
-
DataTableorIDataReader - Column maps you maintain by hand
- No lookup, no error path, no merge
Not only SQL Server
SqlBulkCopy stops at one engine. ETLBox bulk-loads every database we ship a connector for. When the next job is a file, not a table, the same flow reads CSV, Excel, JSON, XML, or Parquet.
Databases
Files and formats
SQL Server, 5,000 rows
From the open benchmark in etlbox.demo. Order of magnitude, not a guarantee. SqlBulkCopy wins the insert by a few milliseconds. Everything else is missing from the class.
| SqlBulkCopy | ETLBox | |
|---|---|---|
| Insert | 20 ms — DataTable, SQL Server | 70 ms — POCOs, same bulk path |
| Update / delete | Not included | DbMerge / BulkUpdate / BulkDelete |
| Upsert / sync | Not included | DbMerge / BulkMerge |
| Other databases | SQL Server only | Postgres COPY, MySQL, Oracle, … |
Method and caveats: how we measured this. We do not claim to beat raw SqlBulkCopy on a SQL Server insert.
Data flow or one method on the connection
Need source → transform → destination? That is ETLBox: DbDestination and DbMerge in a network. Already in Dapper or ADO.NET with a list of POCOs? DbExtensions adds BulkInsert on the same IDbConnection — still SqlBulkCopy on SQL Server.
Keep SqlBulkCopy. Add the rest.
Insert was never the whole job.
A trial key unlocks the full library. NuGet without a key is limited to 5,000 rows per data flow. If you only wanted bulk writes next to Dapper, that page is shorter.
Get a free trial key Dapper + bulk DbDestination docs




