EntityFrameworkCore.SqlServer.SimpleBulks
A very simple .net core library that can help to sync a large number of records in-memory into the database using the SqlBulkCopy class.
Overview
This library provides extension methods so that you can use with your EntityFrameworkCore DbContext instance DbContextExtensions.cs
or you can use SqlConnectionExtensions.cs to work directly with a SqlConnection instance without using EntityFrameworkCore.
Nuget
| Database | Package | GitHub |
|---|---|---|
| SQL Server | EntityFrameworkCore.SqlServer.SimpleBulks | EntityFrameworkCore.SqlServer.SimpleBulks |
| PostgreSQL | EntityFrameworkCore.PostgreSQL.SimpleBulks | EntityFrameworkCore.PostgreSQL.SimpleBulks |
| MySQL | EntityFrameworkCore.MySQL.SimpleBulks | EntityFrameworkCore.MySQL.SimpleBulks |
Features
- Bulk Insert
- Bulk Update
- Bulk Delete
- Bulk Merge
- Bulk Match
- Temp Table
- Direct Insert
- Direct Update
- Direct Delete
Examples
EntityFrameworkCore.SqlServer.SimpleBulks.Demo
- Update the connection string:
private const string _connectionString = \"Server=.;Database=SimpleBulks;User Id=xxx;Password=xxx\";
- Build and run.
DbContextExtensions
Using Lambda Expression
using EntityFrameworkCore.SqlServer.SimpleBulks.BulkDelete; using EntityFrameworkCore.SqlServer.SimpleBulks.BulkInsert; using EntityFrameworkCore.SqlServer.SimpleBulks.BulkMerge; using EntityFrameworkCore.SqlServer.SimpleBulks.BulkUpdate; // Insert all columns dbct.BulkInsert(rows); dbct.BulkInsert(compositeKeyRows); // Insert selected columns only dbct.BulkInsert(rows, row => new { row.Column1, row.Column2, row.Column3 }); dbct.BulkInsert(compositeKeyRows, row => new { row.Id1, row.Id2, row.Column1, row.Column2, row.Column3 }); dbct.BulkUpdate(rows, row => new { row.Column3, row.Column2 }); dbct.BulkUpdate(compositeKeyRows, row => new { row.Column3, row.Column2 }); dbct.BulkMerge(rows, row => row.Id, row => new { row.Column1, row.Column2 }, row => new { row.Column1, row.Column2, row.Column3 }); dbct.BulkMerge(compositeKeyRows, row => new { row.Id1, row.Id2 }, row => new { row.Column1, row.Column2, row.Column3 }, row => new { row.Id1, row.Id2, row.Column1, row.Column2, row.Column3 }); dbct.BulkDelete(rows); dbct.BulkDelete(compositeKeyRows);
Using Dynamic String
using EntityFrameworkCore.SqlServer.SimpleBulks.BulkDelete; using EntityFrameworkCore.SqlServer.SimpleBulks.BulkInsert; using EntityFrameworkCore.SqlServer.SimpleBulks.BulkMerge; using EntityFrameworkCore.SqlServer.SimpleBulks.BulkUpdate; dbct.BulkUpdate(rows, [ \"Column3\", \"Column2\" ]); dbct.BulkUpdate(compositeKeyRows, [ \"Column3\", \"Column2\" ]); dbct.BulkMerge(rows, \"Id\", [ \"Column1\", \"Column2\" ], [ \"Column1\", \"Column2\", \"Column3\" ]); dbct.BulkMerge(compositeKeyRows, [ \"Id1\", \"Id2\" ], [ \"Column1\", \"Column2\", \"Column3\" ], [ \"Id1\", \"Id2\", \"Column1\", \"Column2\", \"Column3\" ]);
Using Builder Approach in case you need to mix both Dynamic & Lambda Expression
new BulkInsertBuilder<Row>(dbct.GetSqlConnection()) .WithColumns(row => new { row.Column1, row.Column2, row.Column3 }) // or .WithColumns([ \"Column1\", \"Column2\", \"Column3\" ]) .WithOutputId(row => row.Id) // or .WithOutputId(\"Id\") .ToTable(dbct.GetTableName(typeof(Row))) // or .ToTable(\"Rows\") .Execute(rows);
SqlConnectionExtensions
Using Lambda Expression
using EntityFrameworkCore.SqlServer.SimpleBulks.BulkDelete; using EntityFrameworkCore.SqlServer.SimpleBulks.BulkInsert; using EntityFrameworkCore.SqlServer.SimpleBulks.BulkMerge; using EntityFrameworkCore.SqlServer.SimpleBulks.BulkUpdate; // Register Type - Table Name globaly TableMapper.Register(typeof(Row), \"Rows\"); TableMapper.Register(typeof(CompositeKeyRow), \"CompositeKeyRows\"); connection.BulkInsert(rows, row => new { row.Column1, row.Column2, row.Column3 }); connection.BulkInsert(compositeKeyRows, row => new { row.Id1, row.Id2, row.Column1, row.Column2, row.Column3 }); connection.BulkUpdate(rows, row => row.Id, row => new { row.Column3, row.Column2 }); connection.BulkUpdate(compositeKeyRows, row => new { row.Id1, row.Id2 }, row => new { row.Column3, row.Column2 }); connection.BulkMerge(rows, row => row.Id, row => new { row.Column1, row.Column2 }, row => new { row.Column1, row.Column2, row.Column3 }); connection.BulkMerge(compositeKeyRows, row => new { row.Id1, row.Id2 }, row => new { row.Column1, row.Column2, row.Column3 }, row => new { row.Id1, row.Id2, row.Column1, row.Column2, row.Column3 }); connection.BulkDelete(rows, row => row.Id); connection.BulkDelete(compositeKeyRows, row => new { row.Id1, row.Id2 });
Using Dynamic String
using EntityFrameworkCore.SqlServer.SimpleBulks.BulkDelete; using EntityFrameworkCore.SqlServer.SimpleBulks.BulkInsert; using EntityFrameworkCore.SqlServer.SimpleBulks.BulkMerge; using EntityFrameworkCore.SqlServer.SimpleBulks.BulkUpdate; connection.BulkInsert(rows, \"Rows\", [ \"Column1\", \"Column2\", \"Column3\" ]); connection.BulkInsert(rows.Take(1000), \"Rows\", typeof(Row).GetDbColumnNames(\"Id\")); connection.BulkInsert(compositeKeyRows, \"CompositeKeyRows\", [ \"Id1\", \"Id2\", \"Column1\", \"Column2\", \"Column3\" ]); connection.BulkUpdate(rows, \"Rows\", \"Id\", [ \"Column3\", \"Column2\" ]); connection.BulkUpdate(compositeKeyRows, \"CompositeKeyRows\", [ \"Id1\", \"Id2\" ], [ \"Column3\", \"Column2\" ]); connection.BulkMerge(rows, \"Rows\", \"Id\", [ \"Column1\", \"Column2\" ], [ \"Column1\", \"Column2\", \"Column3\" ]); connection.BulkMerge(compositeKeyRows, \"CompositeKeyRows\", [ \"Id1\", \"Id2\" ], [ \"Column1\", \"Column2\", \"Column3\" ], [ \"Id1\", \"Id2\", \"Column1\", \"Column2\", \"Column3\" ]); connection.BulkDelete(rows, \"Rows\", \"Id\"); connection.BulkDelete(compositeKeyRows, \"CompositeKeyRows\", [ \"Id1\", \"Id2\" ]);
Using Builder Approach in case you need to mix both Dynamic & Lambda Expression
new BulkInsertBuilder<Row>(connection) .WithColumns(row => new { row.Column1, row.Column2, row.Column3 }) // or .WithColumns([ \"Column1\", \"Column2\", \"Column3\" ]) .WithOutputId(row => row.Id) // or .WithOutputId(\"Id\") .ToTable(\"Rows\") .Execute(rows);
Configuration
BulkInsert
_context.BulkInsert(rows, row => new { row.Column1, row.Column2, row.Column3 }, options => { options.KeepIdentity = false; options.BatchSize = 0; options.Timeout = 30; options.LogTo = Console.WriteLine; });
BulkUpdate
_context.BulkUpdate(rows, row => new { row.Column3, row.Column2 }, options => { options.BatchSize = 0; options.Timeout = 30; options.LogTo = Console.WriteLine; });
BulkDelete
_context.BulkDelete(rows, options => { options.BatchSize = 0; options.Timeout = 30; options.LogTo = Console.WriteLine; });
BulkMerge
_context.BulkMerge(rows, row => row.Id, row => new { row.Column1, row.Column2 }, row => new { row.Column1, row.Column2, row.Column3 }, options => { options.BatchSize = 0; options.Timeout = 30; options.WithHoldLock = false; options.ReturnDbGeneratedId = true; options.LogTo = Console.WriteLine; });
BulkMatch
var contactsFromDb = _context.BulkMatch(matchedContacts, x => new { x.CustomerId, x.CountryIsoCode }, options => { options.BatchSize = 0; options.Timeout = 30; options.LogTo = Console.WriteLine; });
TempTable
var customerTableName = _context.CreateTempTable(customers, x => new { x.IdNumber, x.FirstName, x.LastName, x.CurrentCountryIsoCode }, options => { options.BatchSize = 0; options.Timeout = 30; options.LogTo = Console.WriteLine; });
DirectInsert
_context.DirectInsert(row, row => new { row.Column1, row.Column2, row.Column3 }, options => { options.Timeout = 30; options.LogTo = Console.WriteLine; });
DirectUpdate
_context.DirectUpdate(row, row => new { row.Column3, row.Column2 }, options => { options.Timeout = 30; options.LogTo = Console.WriteLine; });
DirectDelete
_context.DirectDelete(row, options => { options.Timeout = 30; options.LogTo = Console.WriteLine; });
Returned Result
BulkUpdate
var updateResult = dbct.BulkUpdate(rows, row => new { row.Column3, row.Column2 }); Console.WriteLine($\"Updated: {updateResult.AffectedRows} row(s)\");
BulkDelete
var deleteResult = dbct.BulkDelete(rows); Console.WriteLine($\"Deleted: {deleteResult.AffectedRows} row(s)\");
BulkMerge
var mergeResult = dbct.BulkMerge(rows,
row => row.Id,
row => new { row.Column1, row.Column2 },
row => new { row.Column1, row.Column2, row.Column3 });Console.WriteLine($\"Updated: {mergeResult.UpdatedRows} row(s)\");
Console.WriteLine($\"Inserted: {mergeResult.InsertedRows} row(s)\"</
