DuckDbBulkAppender
Bulk writes rows into a DuckDB table using the native DuckDBAppender, used internally by the DuckDB bulk operations.
This class bulk-writes rows into a DuckDB table using the native DuckDBAppender (via DuckDBConnection.CreateAppender()). When every source column maps directly onto a destination column, rows are appended straight into the target table; otherwise, the mapped columns are staged into a temporary table first and copied over with a single INSERT ... SELECT ... ORDER BY rowid.
It is part of RepoDb.DuckDb.BulkOperations and implements IDisposable.
Properties
| Name | Description |
|---|---|
| DestinationTableName | The target table to write to. |
| BulkCopyTimeout | The command timeout, in seconds, applied to the staging/copy commands. Zero (the default) uses the driver default. |
| BatchSize | The number of rows appended before the underlying DuckDBAppender is flushed and re-created. Zero (the default) flushes once at the end. |
| Transaction | The DuckDBTransaction to write under. |
| ColumnMappings | A DuckDbBulkAppenderColumnMappingCollection of explicit source-to-destination column mappings. When left empty, columns are mapped by name (case-insensitive) against the columns that exist on both sides. |
Create a new Instance
using (var connection = new DuckDBConnection(ConnectionString))
{
connection.Open();
using var appender = new DuckDbBulkAppender(connection)
{
DestinationTableName = "Person",
BatchSize = 1000,
BulkCopyTimeout = 120
};
}
Usability
Call WriteToServer()/WriteToServerAsync() with either an IDataReader or a DataTable to write rows. Both overloads return the number of rows written.
Via an IDataReader (e.g. DataEntityDataReader):
using (var connection = new DuckDBConnection(ConnectionString))
{
connection.Open();
var people = GetPeople(100000);
using var reader = new DataEntityDataReader<Person>(people);
using var appender = new DuckDbBulkAppender(connection)
{
DestinationTableName = "Person"
};
var writtenRows = appender.WriteToServer(reader);
}
Via a DataTable:
using (var connection = new DuckDBConnection(ConnectionString))
{
connection.Open();
var table = GetPeopleAsDataTable();
using var appender = new DuckDbBulkAppender(connection)
{
DestinationTableName = "Person"
};
var writtenRows = appender.WriteToServer(table);
}
Optionally, restrict a DataTable write to rows in a specific DataRowState (e.g. only Added rows):
var writtenRows = appender.WriteToServer(table, DataRowState.Added);
With explicit column mappings:
using (var connection = new DuckDBConnection(ConnectionString))
{
connection.Open();
using var appender = new DuckDbBulkAppender(connection)
{
DestinationTableName = "Person"
};
appender.ColumnMappings.Add("FirstName", "FName");
appender.ColumnMappings.Add("LastName", "LName");
var people = GetPeople(100000);
using var reader = new DataEntityDataReader<Person>(people);
var writtenRows = appender.WriteToServer(reader);
}
Every value handed to the appender is converted to the destination column’s CLR type first (e.g.
DateTime→DateOnly,TimeSpan→TimeOnly,string↔Guid) before it is bound — see DuckDbTypeNameToClientTypeResolver for how a column’s CLR type is itself resolved.