ContextBulkExtension 10.0.20

dotnet add package ContextBulkExtension --version 10.0.20
                    
NuGet\Install-Package ContextBulkExtension -Version 10.0.20
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ContextBulkExtension" Version="10.0.20" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ContextBulkExtension" Version="10.0.20" />
                    
Directory.Packages.props
<PackageReference Include="ContextBulkExtension" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ContextBulkExtension --version 10.0.20
                    
#r "nuget: ContextBulkExtension, 10.0.20"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ContextBulkExtension@10.0.20
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ContextBulkExtension&version=10.0.20
                    
Install as a Cake Addin
#tool nuget:?package=ContextBulkExtension&version=10.0.20
                    
Install as a Cake Tool

EF Core Bulk Extension

High-performance bulk operations for Entity Framework Core using SQL Server's SqlBulkCopy.

Installation

Install the NuGet package that matches your EF Core version:

Downloads

# For EF Core 8.x (.NET 8)
dotnet add package ContextBulkExtension --version 8.0.20

# For EF Core 10.x (.NET 10)
dotnet add package ContextBulkExtension --version 10.0.20

Package Structure

This library provides separate NuGet packages for different .NET and EF Core versions:

  • ContextBulkExtension version 8.x.x - For .NET 8 and Entity Framework Core 8.x with SQL Server
  • ContextBulkExtension version 10.x.x - For .NET 10 and Entity Framework Core 10.x with SQL Server

The package uses version-based separation: version numbers starting with 8. target .NET 8, while versions starting with 10. target .NET 10. Both versions share the same PackageId (ContextBulkExtension) but have different version numbers to ensure compatibility with the correct .NET and EF Core versions.

Usage

1. Insert Only

DbContext db = GetYourDbContext();
await db.BulkInsertAsync(entities);

Uses SQL Server's SqlBulkCopy for high-performance bulk inserts. No SQL statement is generated - data is streamed directly to the server using the binary protocol.

2. Upsert with Default Compare

DbContext db = GetYourDbContext();
await db.BulkUpsertAsync(entities);

Compares by primary key and updates all non-key properties.

Generated sql:

-- Creates temporary staging table
CREATE TABLE #TempStaging_... (
    [Id] INT,
    [Name] NVARCHAR(200),
    [Value] INT,
    [CreatedAt] DATETIME2
);

-- Bulk insert into staging table (using SqlBulkCopy)

-- MERGE statement
MERGE [SimpleEntities] AS target
USING #TempStaging_... AS source
ON target.[Id] = source.[Id]
WHEN MATCHED THEN
    UPDATE SET [Name] = source.[Name], [Value] = source.[Value], [CreatedAt] = source.[CreatedAt]
WHEN NOT MATCHED BY TARGET THEN
    INSERT ([Name], [Value], [CreatedAt])
    VALUES (source.[Name], source.[Value], source.[CreatedAt]);

3. Upsert with Advanced Usage

DbContext db = GetYourDbContext();

await db.BulkUpsertAsync(
    entities,
    matchOn: x => new { x.Email, x.Username },
    updateColumns: x => new { x.LastLogin, x.Status }
);

Compares by Email and Username, updates only LastLogin and Status properties.

Generated sql:

-- Creates temporary staging table
CREATE TABLE #TempStaging_... (
    [Id] INT,
    [Email] NVARCHAR(255),
    [Username] NVARCHAR(100),
    [FirstName] NVARCHAR(100),
    [LastName] NVARCHAR(100),
    [LastLogin] DATETIME2,
    [Status] NVARCHAR(50),
    [RegisteredAt] DATETIME2
);

-- Bulk insert into staging table (using SqlBulkCopy)

-- MERGE statement with custom match and update columns
MERGE [UserEntities] AS target
USING #TempStaging_... AS source
ON target.[Email] = source.[Email] AND target.[Username] = source.[Username]
WHEN MATCHED THEN
    UPDATE SET [LastLogin] = source.[LastLogin], [Status] = source.[Status]
WHEN NOT MATCHED BY TARGET THEN
    INSERT ([Email], [Username], [FirstName], [LastName], [LastLogin], [Status], [RegisteredAt])
    VALUES (source.[Email], source.[Username], source.[FirstName], source.[LastName], source.[LastLogin], source.[Status], source.[RegisteredAt]);

4. Upsert with deletion

Performs upsert operations and optionally deletes records in the target table that don't exist in the source batch.

DbContext db = GetYourDbContext();

// Delete records not in source, scoped to specific account
await db.BulkUpsertWithDeleteScopeAsync(
    entities,
    matchOn: x => new { x.AccountId, x.Metric, x.Date },
    deleteScope: x => x.AccountId == 123 && x.Category == "Energy"
);

⚠️ Important: When deleteScope is null, ALL records in the target table that don't match ANY row in the source batch will be deleted. Always provide a deleteScope to limit deletions to a specific subset (e.g., specific account, date range, or category).

Generated sql:

-- Creates temporary staging table
CREATE TABLE #TempStaging_... (
    [Id] INT,
    [AccountId] INT,
    [Metric] NVARCHAR(100),
    [Date] DATETIME2,
    [Value] DECIMAL(18,2),
    [Category] NVARCHAR(100)
);

-- Bulk insert into staging table (using SqlBulkCopy)

-- MERGE statement with deletion
MERGE [MetricEntities] AS target
USING #TempStaging_... AS source
ON target.[AccountId] = source.[AccountId] 
   AND target.[Metric] = source.[Metric] 
   AND target.[Date] = source.[Date]
WHEN MATCHED THEN
    UPDATE SET [Value] = source.[Value], [Category] = source.[Category]
WHEN NOT MATCHED BY TARGET THEN
    INSERT ([AccountId], [Metric], [Date], [Value], [Category])
    VALUES (source.[AccountId], source.[Metric], source.[Date], source.[Value], source.[Category])
WHEN NOT MATCHED BY SOURCE AND [AccountId] = @p0 AND [Category] = @p1 THEN
    DELETE;

Parameters:

  • matchOn: Expression specifying which columns to match on (defaults to primary key)
  • updateColumns: Expression specifying which columns to update on match (defaults to all non-key columns)
  • deleteScope: Optional expression to scope which records can be deleted (e.g., x => x.AccountId == 123)

Roadmap

  • BulkMerge cancelled, use BulkUpsert instead
  • Identity output
  • Upsert with deletion
  • Benchmark with large dataset and table with 20+ columns
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on ContextBulkExtension:

Package Downloads
ContextBulkExtension.SqlServer.v8

High-performance bulk operations for Entity Framework Core using SQL Server's SqlBulkCopy. Designed for efficiently inserting millions of records.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.0.20 61 1/17/2026
8.0.20 58 1/17/2026