Skip to content

SqlBulkCopy executes metadata queries multiple times per operation despite providing column mappingsΒ #3627

@paullpra

Description

@paullpra

SqlBulkCopy executes metadata queries multiple times per operation despite providing column mappings

Summary

SqlBulkCopy executes metadata queries 5 times for each bulk insert operation, even when column mappings and data table schema are explicitly provided. This causes significant performance degradation in high-frequency bulk insert scenarios.

Problem Description

When using SqlBulkCopy with explicit column mappings and a properly structured DataTable, the following metadata query is still executed 5 times per bulk insert operation:

select @@trancount; SET FMTONLY ON select * from [TableName] SET FMTONLY OFF exec ..sp_tablecollations_100 N'.[TableName]'

Expected Behavior: When metadata (column mappings, DataTable schema) is provided explicitly, these metadata discovery queries should be skipped.

Actual Behavior: Metadata queries are executed 5 times for every single bulk insert operation, regardless of provided metadata.

Performance Impact

  • Each metadata query adds network round-trip latency
  • In high-frequency scenarios (continuous bulk inserts), this creates significant overhead
  • Database server experiences unnecessary query load

Code Example

using var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, transaction);
bulkCopy.DestinationTableName = "Users";

// Explicit column mappings provided
bulkCopy.ColumnMappings.Add("FirstName", "FirstName");
bulkCopy.ColumnMappings.Add("LastName", "LastName");
bulkCopy.ColumnMappings.Add("Email", "Email");
bulkCopy.ColumnMappings.Add("Age", "Age");
// ... additional mappings for all columns

// DataTable with proper schema that matches target table
var dataTable = new DataTable();
dataTable.Columns.Add("FirstName", typeof(string));
dataTable.Columns.Add("LastName", typeof(string));
dataTable.Columns.Add("Email", typeof(string));
dataTable.Columns.Add("Age", typeof(int));
// ... additional columns match target table exactly

// Additional configuration attempts
bulkCopy.EnableStreaming = true;
bulkCopy.BatchSize = 1000;

await bulkCopy.WriteToServerAsync(dataTable, cancellationToken);
// ↑ This still triggers 5 metadata queries despite explicit mappings

Reproduction

A complete reproduction case is available at: https://github.com/paullpra/SqlBulkCopyMetaDataQueryIssue/tree/main/BulkInsertIssue

The sample application demonstrates:

  • Explicit column mappings for all columns
  • Proper DataTable schema configuration
  • Extended event sessions showing repeated metadata queries

Environment

  • .NET Version: net8.0
  • Microsoft.Data.SqlClient version: 5.2.2

Attempted Workarounds

We have tried the following configurations without success in preventing the metadata queries:

  1. Explicit Column Mappings: Added mappings for every single column
  2. SqlBulkCopyOptions combinations:
    • SqlBulkCopyOptions.TableLock
    • SqlBulkCopyOptions.Default
    • SqlBulkCopyOptions.KeepIdentity
  3. DataTable Schema: Pre-defined schema to exactly match target table structure
  4. Streaming: EnableStreaming = true
  5. Batch Configuration: Various batch sizes

None of these approaches prevent the metadata discovery queries from being executed repeatedly.

Expected Solution

  1. Skip metadata queries when explicit column mappings are provided for all columns

Business Impact

This issue significantly affects applications that:

  • Perform high-frequency bulk inserts (logging, telemetry, ETL)
  • Process data in real-time with continuous inserts
  • Require low-latency bulk operations
  • Handle large volumes of data where every millisecond counts

Logs/Traces

When running SQL Profiler or Extended Events, the following pattern is observed for each WriteToServerAsync call:

Image

This pattern repeats for every single bulk insert operation, even when performed in rapid succession on the same table.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions