Bulk Options

Bulk operations in ETLBox.DbExtensions can be customized using the BulkOptions or MergeBulkOptions classes. These options allow fine-tuned control over how data is inserted, updated, or deleted during a bulk operation.

This article describes all available options for BulkInsert(), BulkUpdate(), and BulkDelete() via BulkOptions<T>, and explains which options apply specifically to BulkMerge() via MergeBulkOptions<T>.

Usage Example

connection.BulkInsert(customers, options => {
    options.BatchSize = 1000;
    options.TablePrefix = "dim";
    options.ReadGeneratedValues = true;
    options.AllowIdentityInsert = true;
    options.OnProgress = rows => Console.WriteLine($"Inserted {rows} rows.");
});

Shared Options

These options are available in both BulkOptions<T> and MergeBulkOptions<T>:

PropertyDescription
BatchSizeNumber of records per batch. Default is 1000.
ReadGeneratedValuesIf true, reads auto-generated values (e.g. identity columns). Only supported on some DBMSs.
AllowIdentityInsertEnables manual values in identity/serial columns.
OnProgressCallback after each batch with number of rows processed.
RedirectErroneousBatchesIf true, continues after errors and stores failures in ErrorData.
ErrorDataHolds information about failed rows when redirection is enabled.
ColumnConvertersList of value converters for specific columns.
ColumnMappingCustom mapping of class properties to database columns.
TableNameOverrides the target table name entirely.
TablePrefix / TableSuffixPrefix/suffix added to the default table name.
IgnoreDefaultColumnsOnInsertIgnores DB columns with a DEFAULT constraint when inserting.
IdColumnsDefines primary key columns used for update/delete/merge operations.

Options for Insert/Update/Delete

These apply only to BulkInsert(), BulkUpdate(), and BulkDelete():

PropertyDescription
BeforeBatchWriteFunction executed before each batch is written. Can transform the batch.
AfterBatchWriteAction executed after a batch has been written.
UpdateColumnsExplicitly specify which columns to update (optional). Applies to update operations only.

Examples for Bulk Options

The following examples apply to BulkInsert, BulkUpdate, and BulkDelete. Examples for BulkMerge options are provided in the section below.

OnProgress

connection.BulkInsert(data, options => {
    options.OnProgress = count => {
        Console.WriteLine($"{count} rows processed.");
    };
});

RedirectErroneousBatches / ErrorData

Skip failed batches and collect errors for inspection:

var errorList = new List<ETLBoxError>();

connection.BulkInsert(data, options => {
    options.RedirectErroneousBatches = true;
    options.ErrorData = errorList;
});

// Handle/log errors
foreach (var error in errorList)
    Console.WriteLine($"Error: {error.ErrorText}, Failing Data: {error.RecordAsJson}");

ColumnConverters

Transform values before writing them to the database:

connection.BulkInsert(data, options => {
    options.ColumnConverters = new[] {
        new ColumnConverter("Url", val => "PRE_" + val?.ToString())
    };
});

ColumnMapping

Map property names to different database column names, or ignore properties:

connection.BulkInsert(data, options => {
    options.ColumnMapping = new[] {
        new DbColumnMap { PropertyName = "InternalName", DbColumnName = "DisplayName" },
        new DbColumnMap { PropertyName = "TempFlag", IgnoreColumn = true }
    };
});

BeforeBatchWrite / AfterBatchWrite

Use these callbacks to run custom logic before and after each batch is processed.

connection.BulkUpdate(data, options => {
    options.BatchSize = 100;

    options.BeforeBatchWrite = batch => {
        Console.WriteLine($"Preparing batch of {batch.Length} records...");
        return batch;
    };

    options.AfterBatchWrite = batch => {
        Console.WriteLine($"Finished batch of {batch.Length} records.");
    };
});

UpdateColumns

Specify exactly which properties should be updated when a matching row is found.

connection.BulkUpdate(data, options => {
    options.IdColumns = new[] { new IdColumn("Id") };
    options.UpdateColumns = new[] {
        new UpdateColumn("City"),
        new UpdateColumn("Name")
    };
});

Additional Options for BulkMerge

These options are available only for BulkMerge():

PropertyDescription
MergeModeEither MergeMode.Full (default), MergeMode.Delta, MergeMode.InsertsOnly, MergeMode.UpdatesOnly or MergeMode.InsertsAndDeletes. Determines deletion behavior.
FindDuplicatesEnables duplicate detection in source data.
CompareColumnsColumns used to decide if a row needs to be updated.
UpdateColumnsColumns to be updated when a match is found.
DeleteColumnsUsed in Delta mode to determine which rows to delete.
CompareFuncCustom comparison function for update detection.
CacheModeFull or Partial. Controls how much of the target table is cached for comparisons.
MaxCacheSizeLimit the number of records held in memory for merge.
EvictionPolicyControls how cached data is refreshed during a partial merge.
ReadConnectionUsed only with CacheMode.Partial. A separate connection is required to read from the target table while writing.

Additional Examples for BulkMerge

FindDuplicates

Enable this option to automatically detect and skip duplicate records in the source data based on the ID columns.

connection.BulkMerge(data, options => {
    options.MergeMode = MergeMode.Full;
    options.FindDuplicates = true;
});

CompareFunc

Use CompareFunc to override comparison logic — for example, always force an update if a matching row exists.

connection.BulkMerge(data, options => {
    options.MergeMode = MergeMode.InsertsAndUpdates;
    options.IdColumns = new[] {
        new IdColumn("Id1"),
        new IdColumn("OtherId")
    };
    options.CompareFunc = (source, target) => {
        // Always update if the record exists
        return false;
    };
});

Let me know if you want a version that conditionally compares values (e.g., only update if one column differs).