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.

ETLBox

Bulk, then the rest of ETL

  • SqlBulkCopy on SQL Server inserts
  • POCOs — no DataTable
  • DbMerge for upsert and sync
  • Every database we ship a connector for — and files when you switch
  • Same engine in a data flow or on IDbConnection
SqlBulkCopy

One operation, one database

  • Insert only
  • SQL Server only
  • DataTable or IDataReader
  • 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

SQL Server SQL Server
Azure SQL Azure SQL
PostgreSQL PostgreSQL
Oracle Oracle
MySQL MySQL
MariaDB MariaDB
SQLite SQLite
IBM Db2 IBM Db2
SAP ASE SAP ASE
SAP HANA SAP HANA
Snowflake Snowflake
ClickHouse ClickHouse
Microsoft Access Microsoft Access
Apache Spark Apache Spark
ODBC ODBC
OLE DB OLE DB

Files and formats

CSV CSV
Excel Excel
JSON JSON
XML XML
Parquet Parquet
Text Text

Database connectors · Streaming connectors

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.

SqlBulkCopyETLBox
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

Commonwealth Bank of Australia
Australia

Brunata
Denmark

Deloitte
Ireland, India

IWG
Switzerland

National Bank of Serbia
Serbia

Flowwright
USA

FASTEC
Germany

Calpine Energy Solutions
USA

Digitain
Armenia

Health Catalyst
USA

Regal Rexnord
USA, Mexiko

Normandin Beaudry
Canada

Djøf
Denmark

ATD Solutions Ltd.
U.K.