### Configuration Options for TempTable Creation Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Details the configuration options for creating temporary tables, including batch size, timeout, and logging. This is useful for staging data before further processing. ```csharp 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; }); ``` -------------------------------- ### Configuration Options for BulkMatch Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Explains the configuration options for BulkMatch, focusing on batch size, timeout, and logging. This helps in efficiently matching records between the application and the database. ```csharp var contactsFromDb = _context.BulkMatch(matchedContacts, x => new { x.CustomerId, x.CountryIsoCode }, options => { options.BatchSize = 0; options.Timeout = 30; options.LogTo = Console.WriteLine; }); ``` -------------------------------- ### Configuration Options for BulkDelete Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Illustrates configuration options for BulkDelete, including batch size, timeout, and logging. These parameters control the execution and monitoring of delete operations. ```csharp _context.BulkDelete(rows, options => { options.BatchSize = 0; options.Timeout = 30; options.LogTo = Console.WriteLine; }); ``` -------------------------------- ### Builder Approach for Mixed Operations Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Illustrates the builder pattern for constructing bulk operations, allowing a mix of lambda expressions and dynamic strings for column and key specifications. This provides flexibility in defining operations. ```csharp new BulkInsertBuilder(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); ``` -------------------------------- ### Bulk Insert Builder Approach Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Demonstrates using the BulkInsertBuilder for more complex scenarios, allowing specification of columns, output IDs, and target tables using both lambda expressions and dynamic strings. ```C# new BulkInsertBuilder(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); ``` -------------------------------- ### Configuration Options for BulkUpdate Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Shows how to configure options for the BulkUpdate operation, such as batch size, timeout, and logging. These settings help manage the update process efficiently. ```csharp _context.BulkUpdate(rows, row => new { row.Column3, row.Column2 }, options => { options.BatchSize = 0; options.Timeout = 30; options.LogTo = Console.WriteLine; }); ``` -------------------------------- ### Configuration Options for BulkInsert Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Demonstrates how to configure options for the BulkInsert operation, including keeping identity, batch size, timeout, and logging. These options allow fine-tuning of the insert process. ```csharp _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; }); ``` -------------------------------- ### Bulk Operations with Lambda Expressions Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Shows how to perform bulk insert, update, merge, and delete operations using lambda expressions to specify columns and keys. This approach leverages type safety and IntelliSense. ```csharp 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 }); ``` -------------------------------- ### CreateTempTable Performance Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Benchmarks for the CreateTempTable operation, illustrating performance metrics (Mean, Gen0, Gen1, Gen2, Allocated) for various row counts. This is essential for understanding temporary data handling efficiency. ```ini BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19045.5011) 11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores .NET SDK=8.0.400 [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 Job-LGAVYD : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 InvocationCount=1 IterationCount=1 UnrollFactor=1 WarmupCount=0 | Method | RowsCount | Mean | Error | Gen0 | Gen1 | Gen2 | Allocated | |---------------- |---------- |-------------:|------:|-----------:|-----------:|----------:|-------------:| | **CreateTempTable** | **100** | **7.639 ms** | **NA** | **-** | **-** | **-** | **68.03 KB** | | **CreateTempTable** | **1000** | **14.077 ms** | **NA** | **-** | **-** | **-** | **373.76 KB** | | **CreateTempTable** | **10000** | **89.789 ms** | **NA** | **-** | **-** | **-** | **3455.46 KB** | | **CreateTempTable** | **100000** | **574.937 ms** | **NA** | **4000.0000** | **1000.0000** | **-** | **34081.95 KB** | | **CreateTempTable** | **250000** | **1,403.071 ms** | **NA** | **12000.0000** | **5000.0000** | **1000.0000** | **85229.91 KB** | | **CreateTempTable** | **500000** | **2,838.562 ms** | **NA** | **22000.0000** | **8000.0000** | **1000.0000** | **170241.85 KB** | | **CreateTempTable** | **1000000** | **6,198.206 ms** | **NA** | **43000.0000** | **14000.0000** | **1000.0000** | **340282.7 KB** | ``` -------------------------------- ### BulkUpdate Performance Benchmarks Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Benchmark results comparing EFCoreUpdate and BulkUpdate for different row counts. Shows mean execution time, memory allocation (Gen0, Gen1), and error rates. BulkUpdate consistently outperforms EFCoreUpdate. ```ini BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19045.5011) 11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores .NET SDK=8.0.400 [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 Job-LGAVYD : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 InvocationCount=1 IterationCount=1 UnrollFactor=1 WarmupCount=0 | Method | RowsCount | Mean | Error | Gen0 | Gen1 | Allocated | |-------------:|---------- |-------------:|------:|------------:|-----------:|--------------:| | **EFCoreUpdate** | **100** | **61.65 ms** | **NA** | **-** | **-** | **853.66 KB** | | BulkUpdate | 100 | 27.33 ms | NA | - | - | 63.55 KB | | **EFCoreUpdate** | **1000** | **143.39 ms** | **NA** | **1000.0000** | **-** | **8398.1 KB** | | BulkUpdate | 1000 | 43.95 ms | NA | - | - | 379.25 KB | | **EFCoreUpdate** | **10000** | **685.97 ms** | **NA** | **12000.0000** | **3000.0000** | **82396.19 KB** | | BulkUpdate | 10000 | 182.54 ms | NA | - | - | 3499.74 KB | | **EFCoreUpdate** | **100000** | **8,495.18 ms** | **NA** | **120000.0000** | **28000.0000** | **810248.07 KB** | | BulkUpdate | 100000 | 2,091.42 ms | NA | 5000.0000 | 1000.0000 | 33819.46 KB | | **EFCoreUpdate** | **250000** | **17,859.49 ms** | **NA** | **300000.0000** | **69000.0000** | **2005895.77 KB** | | BulkUpdate | 250000 | 4,290.07 ms | NA | 13000.0000 | 7000.0000 | 84352 KB | ``` ```ini BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19045.5011) 11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores .NET SDK=8.0.400 [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 Job-LGAVYD : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 InvocationCount=1 IterationCount=1 UnrollFactor=1 WarmupCount=0 | Method | RowsCount | Mean | Error | Gen0 | Gen1 | Allocated | |----------- |---------- |--------:|------:|-----------:|-----------:|----------:| | **BulkUpdate** | **500000** | **10.19 s** | **NA** | **27000.0000** | **16000.0000** | **164.63 MB** | | **BulkUpdate** | **1000000** | **17.03 s** | **NA** | **54000.0000** | **37000.0000** | **329.12 MB** | ``` -------------------------------- ### Configuration Options for DirectInsert Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Shows how to configure options for DirectInsert, such as timeout and logging. This method is suitable for inserting single records efficiently. ```csharp _context.DirectInsert(row, row => new { row.Column1, row.Column2, row.Column3 }, options => { options.Timeout = 30; options.LogTo = Console.WriteLine; }); ``` -------------------------------- ### BulkDelete Benchmark Results (100000-1000000 Rows) Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md This benchmark extends the comparison of EFCore's standard delete versus SimpleBulks' BulkDelete for larger datasets. The results continue to demonstrate SimpleBulks' superior performance and efficiency in handling bulk delete operations, with significantly lower execution times and memory allocations compared to the standard EFCore approach. ```ini BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19045.5011) 11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores .NET SDK=8.0.400 [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 Job-LGAVYD : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 InvocationCount=1 IterationCount=1 UnrollFactor=1 WarmupCount=0 | Method | RowsCount | Mean | Error | Gen0 | Gen1 | Allocated | |-----------:|----------:|-----------:|------:|-----------:|-----------:|----------:| | **BulkDelete** | **100000** | **937.7 ms** | **NA** | **3000.0000** | **1000.0000** | **20.67 MB** | | **BulkDelete** | **250000** | **2,619.7 ms** | **NA** | **7000.0000** | **3000.0000** | **51.7 MB** | | **BulkDelete** | **500000** | **4,897.7 ms** | **NA** | **13000.0000** | **6000.0000** | **103.22 MB** | | **BulkDelete** | **1000000** | **9,466.0 ms** | **NA** | **26000.0000** | **12000.0000** | **206.28 MB** | ``` -------------------------------- ### Bulk Operations with Dynamic Strings Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Demonstrates performing bulk operations using dynamic string arrays for table names and column names. This method is useful when the schema is not known at compile time or for dynamic scenarios. ```csharp 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" ]); ``` -------------------------------- ### Configuration Options for BulkMerge Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Details the configuration options available for BulkMerge, including batch size, timeout, locking behavior, returning generated IDs, and logging. This allows for complex merge strategies. ```csharp _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 Multiple Columns Performance Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Evaluates the performance of BulkMatch against EFCoreSelect for multiple-column operations across various row counts. The benchmarks highlight execution time, memory usage, and GC impact. ```ini BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19045.5011) 11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores .NET SDK=8.0.400 [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 Job-LGAVYD : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 InvocationCount=1 IterationCount=1 UnrollFactor=1 WarmupCount=0 | Method | RowsCount | Mean | Error | Gen0 | Gen1 | Allocated | |------------- |---------- |-------------:|------:|------------:|-----------:|--------------:| | **EFCoreSelect** | **100** | **130.11 ms** | **NA** | **-** | **-** | **1256.8 KB** | | BulkMatch | 100 | 15.46 ms | NA | - | - | 173.56 KB | | **EFCoreSelect** | **1000** | **997.87 ms** | **NA** | **2000.0000** | **-** | **12373.85 KB** | | BulkMatch | 1000 | 43.35 ms | NA | - | - | 1358.77 KB | | **EFCoreSelect** | **10000** | **9,769.96 ms** | **NA** | **20000.0000** | **4000.0000** | **123595.97 KB** | | BulkMatch | 10000 | 238.80 ms | NA | 2000.0000 | 1000.0000 | 13768.49 KB | ``` -------------------------------- ### BulkDelete Benchmark Results (100-50000 Rows) Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md This benchmark compares the performance of EFCore's standard delete method against SimpleBulks' BulkDelete method for deleting records from a SQL Server database. The results show significant performance improvements with SimpleBulks, especially as the number of rows increases. Metrics include mean execution time, GC generation counts, and memory allocation. ```ini BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19045.5011) 11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores .NET SDK=8.0.400 [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 Job-LGAVYD : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 InvocationCount=1 IterationCount=1 UnrollFactor=1 WarmupCount=0 | Method | RowsCount | Mean | Error | Gen0 | Gen1 | Allocated | |-------------:|----------:|-------------:|------:|-----------:|-----------:|-------------:| | **EFCoreDelete** | **100** | **73.25 ms** | **NA** | **-** | **-** | **681.09 KB** | | BulkDelete | 100 | 29.42 ms | NA | - | - | 43.45 KB | | **EFCoreDelete** | **1000** | **176.83 ms** | **NA** | **1000.0000** | **1000.0000** | **6745 KB** | | BulkDelete | 1000 | 27.19 ms | NA | - | - | 236.86 KB | | **EFCoreDelete** | **10000** | **1,489.03 ms** | **NA** | **10000.0000** | **2000.0000** | **66031.55 KB** | | BulkDelete | 10000 | 431.74 ms | NA | - | - | 2150.99 KB | | **EFCoreDelete** | **20000** | **6,084.87 ms** | **NA** | **20000.0000** | **7000.0000** | **132403.3 KB** | | BulkDelete | 20000 | 276.52 ms | NA | - | - | 4276.01 KB | | **EFCoreDelete** | **50000** | **39,933.60 ms** | **NA** | **49000.0000** | **14000.0000** | **326164.25 KB** | | BulkDelete | 50000 | 1,477.09 ms | NA | 1000.0000 | - | 10594.63 KB | ``` -------------------------------- ### BulkMatch Performance Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Benchmarks for the BulkMatch operation, showing performance metrics (Mean, Gen0, Gen1, Allocated) for different row counts. This operation is crucial for efficient data matching in bulk. ```ini BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19045.5011) 11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores .NET SDK=8.0.400 [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 Job-LGAVYD : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 InvocationCount=1 IterationCount=1 UnrollFactor=1 WarmupCount=0 | Method | RowsCount | Mean | Error | Gen0 | Gen1 | Allocated | |---------- |---------- |---------:|------:|------------:|-----------:|-----------:| | **BulkMatch** | **250000** | **6.709 s** | **NA** | **53000.0000** | **19000.0000** | **340.68 MB** | | **BulkMatch** | **500000** | **12.939 s** | **NA** | **107000.0000** | **36000.0000** | **683.46 MB** | | **BulkMatch** | **1000000** | **25.418 s** | **NA** | **214000.0000** | **74000.0000** | **1369.34 MB** | ``` -------------------------------- ### BulkMatch Single Column Performance Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Compares the performance of BulkMatch against EFCoreSelect and EFCoreBatchSelect for single-column operations across different row counts. The benchmarks measure mean execution time, memory allocation, and garbage collection generations. ```ini BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19045.5011) 11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores .NET SDK=8.0.400 [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 Job-LGAVYD : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 InvocationCount=1 IterationCount=1 UnrollFactor=1 WarmupCount=0 | Method | RowsCount | Mean | Error | Gen0 | Gen1 | Gen2 | Allocated | |------------------ |---------- |--------------:|------:|------------:|-----------:|----------:|------------:| | **EFCoreSelect** | **100** | **97.373 ms** | **NA** | **-** | **-** | **-** | **1008.33 KB** | | EFCoreBatchSelect | 100 | 7.166 ms | NA | - | - | - | 94.77 KB | | BulkMatch | 100 | 8.570 ms | NA | - | - | - | 106.63 KB | | **EFCoreSelect** | **1000** | **720.250 ms** | **NA** | **1000.0000** | **-** | **-** | **9761.42 KB** | | EFCoreBatchSelect | 1000 | 6.375 ms | NA | - | - | - | 908.18 KB | | BulkMatch | 1000 | 15.445 ms | NA | - | - | - | 820.36 KB | | **EFCoreSelect** | **10000** | **8,075.686 ms** | **NA** | **15000.0000** | **1000.0000** | **-** | **97115.62 KB** | | EFCoreBatchSelect | 10000 | 66.438 ms | NA | 1000.0000 | - | - | 9092.91 KB | | BulkMatch | 10000 | 69.430 ms | NA | 1000.0000 | - | - | 8177.76 KB | | **EFCoreSelect** | **100000** | **81,088.718 ms** | **NA** | **159000.0000** | **31000.0000** | **1000.0000** | **972204.7 KB** | | EFCoreBatchSelect | 100000 | 920.412 ms | NA | 11000.0000 | 4000.0000 | 1000.0000 | 91808.56 KB | | BulkMatch | 100000 | 742.030 ms | NA | 13000.0000 | 6000.0000 | 1000.0000 | 82419.43 KB | BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19045.5011) 11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores .NET SDK=8.0.400 [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 Job-LGAVYD : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 InvocationCount=1 IterationCount=1 UnrollFactor=1 WarmupCount=0 | Method | RowsCount | Mean | Error | Gen0 | Gen1 | Gen2 | Allocated | |------------------ |---------- |---------:|------:|------------:|-----------:|----------:|----------:| | **EFCoreBatchSelect** | **250000** | **2.101 s** | **NA** | **26000.0000** | **11000.0000** | **1000.0000** | **224.05 MB** | | BulkMatch | 250000 | 2.067 s | NA | 32000.0000 | 12000.0000 | 1000.0000 | 201.64 MB | | **EFCoreBatchSelect** | **500000** | **4.239 s** | **NA** | **53000.0000** | **20000.0000** | **2000.0000** | **448.85 MB** | | BulkMatch | 500000 | 4.507 s | NA | 62000.0000 | 24000.0000 | 1000.0000 | 404.03 MB | | **EFCoreBatchSelect** | **1000000** | **8.523 s** | **NA** | **103000.0000** | **38000.0000** | **1000.0000** | **898.44 MB** | | BulkMatch | 1000000 | 11.585 s | NA | 123000.0000 | 46000.0000 | 1000.0000 | 808.82 MB | ``` -------------------------------- ### Bulk Insert vs EF Core Insert (Single Table) Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Compares the performance of BulkInsert against EFCoreInsert for inserting data into a single table. The benchmark measures mean execution time, memory allocation, and garbage collection generations across different row counts. ```ini BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19045.5011) 11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores .NET SDK=8.0.400 [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 Job-LGAVYD : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 InvocationCount=1 IterationCount=1 UnrollFactor=1 WarmupCount=0 | Method | RowsCount | Mean | Error | Gen0 | Gen1 | Gen2 | Allocated | |-------------:|----------:|-------------:|------:|------------:|------------:|----------:|--------------:| | **EFCoreInsert** | **100** | **45.19 ms** | **NA** | **-** | **-** | **-** | **985.52 KB** | | BulkInsert | 100 | 32.68 ms | NA | - | - | - | 93.78 KB | | **EFCoreInsert** | **1000** | **145.41 ms** | **NA** | **1000.0000** | **-** | **-** | **9702.7 KB** | | BulkInsert | 1000 | 44.94 ms | NA | - | - | - | 573.84 KB | | **EFCoreInsert** | **10000** | **788.90 ms** | **NA** | **14000.0000** | **5000.0000** | **-** | **95727.38 KB** | | BulkInsert | 10000 | 126.36 ms | NA | - | - | - | 5320.53 KB | | **EFCoreInsert** | **100000** | **7,107.29 ms** | **NA** | **146000.0000** | **36000.0000** | **-** | **950162.56 KB** | | BulkInsert | 100000 | 998.42 ms | NA | 7000.0000 | 3000.0000 | 1000.0000 | 51730.81 KB | | **EFCoreInsert** | **250000** | **18,542.56 ms** | **NA** | **365000.0000** | **87000.0000** | **-** | **2352262.34 KB** | | BulkInsert | 250000 | 2,576.88 ms | NA | 16000.0000 | 5000.0000 | 1000.0000 | 125832.63 KB | | **EFCoreInsert** | **500000** | **34,957.34 ms** | **NA** | **730000.0000** | **170000.0000** | **-** | **4711772.88 KB** | | BulkInsert | 500000 | 5,553.61 ms | NA | 30000.0000 | 9000.0000 | 1000.0000 | 252707.77 KB | ``` -------------------------------- ### BulkMerge vs EFCoreUpsert Performance Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md This benchmark compares the performance of BulkMerge with EFCoreUpsert for different row counts. It measures execution time (Mean) and memory allocation (Allocated), highlighting BulkMerge's efficiency. ```ini BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19045.5011) 11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores .NET SDK=8.0.400 [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 Job-LGAVYD : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 InvocationCount=1 IterationCount=1 UnrollFactor=1 WarmupCount=0 | Method | RowsCount | Mean | Error | Gen0 | Gen1 | Gen2 | Allocated | |-------------:|---------- |-------------:|------:|------------:|------------:|----------:|--------------:| | **EFCoreUpsert** | **100** | **82.11 ms** | **NA** | **-** | **-** | **-** | **1840.23 KB** | | BulkMerge | 100 | 34.27 ms | NA | - | - | - | 162.96 KB | | **EFCoreUpsert** | **1000** | **266.86 ms** | **NA** | **2000.0000** | **1000.0000** | **-** | **17984.91 KB** | | BulkMerge | 1000 | 79.45 ms | NA | - | - | - | 1213.33 KB | | **EFCoreUpsert** | **10000** | **1,451.20 ms** | **NA** | **26000.0000** | **8000.0000** | **-** | **178385.15 KB** | | BulkMerge | 10000 | 677.47 ms | NA | 1000.0000 | - | - | 11679.42 KB | | **EFCoreUpsert** | **100000** | **13,902.06 ms** | **NA** | **266000.0000** | **63000.0000** | **-** | **1762696.52 KB** | | BulkMerge | 100000 | 3,415.31 ms | NA | 16000.0000 | 6000.0000 | 1000.0000 | 115233.2 KB | | **EFCoreUpsert** | **250000** | **36,167.51 ms** | **NA** | **665000.0000** | **152000.0000** | **-** | **4362872.57 KB** | | BulkMerge | 250000 | 7,681.71 ms | NA | 37000.0000 | 11000.0000 | 1000.0000 | 284187.09 KB | ``` -------------------------------- ### Bulk Insert vs EF Core Insert (Multiple Tables) Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Compares the performance of BulkInsert against EFCoreInsert for inserting data into multiple related tables (1 parent + 5 child rows). The benchmark measures mean execution time, memory allocation, and garbage collection generations across different row counts. ```ini BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19045.5011) 11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores .NET SDK=8.0.400 [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 Job-LGAVYD : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 InvocationCount=1 IterationCount=1 UnrollFactor=1 WarmupCount=0 | Method | RowsCount | Mean | Error | Gen0 | Gen1 | Gen2 | Allocated | |-------------:|----------:|-------------:|------:|-------------:|------------:|----------:|--------------:| | **EFCoreInsert** | **100** | **226.22 ms** | **NA** | **1000.0000** | **-** | **-** | **7438.51 KB** | | BulkInsert | 100 | 48.38 ms | NA | - | - | - | 444.18 KB | | **EFCoreInsert** | **1000** | **566.95 ms** | **NA** | **11000.0000** | **4000.0000** | **-** | **73518.48 KB** | | BulkInsert | 1000 | 125.77 ms | NA | - | - | - | 3460.21 KB | | **EFCoreInsert** | **10000** | **6,268.42 ms** | **NA** | **114000.0000** | **30000.0000** | **-** | **731076.92 KB** | | BulkInsert | 10000 | 1,066.74 ms | NA | 5000.0000 | 2000.0000 | 1000.0000 | 33324.16 KB | | **EFCoreInsert** | **100000** | **59,389.89 ms** | **NA** | **1138000.0000** | **264000.0000** | **-** | **7282561.93 KB** | | BulkInsert | 100000 | 9,504.12 ms | NA | 39000.0000 | 13000.0000 | 1000.0000 | 327100.08 KB | ``` -------------------------------- ### Direct Update with Entity Framework Core Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Performs a direct update operation on a single row using Entity Framework Core. Allows specifying columns to update and configuring execution options like timeout and logging. ```csharp _context.DirectUpdate(row, row => new { row.Column3, row.Column2 }, options => { options.Timeout = 30; options.LogTo = Console.WriteLine; }); ``` -------------------------------- ### Bulk Merge with Entity Framework Core Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Performs a bulk merge (upsert) operation on multiple rows using Entity Framework Core. Specifies the key selector, columns for update, and columns for insert. ```csharp 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)"); Console.WriteLine($"Affected: {mergeResult.AffectedRows} row(s)"); ``` -------------------------------- ### Bulk Update with Entity Framework Core Source: https://github.com/phongnguyend/entityframeworkcore.sqlserver.simplebulks/blob/master/README.md Performs a bulk update operation on multiple rows using Entity Framework Core. Specifies the rows to update and the columns to include in the update. ```csharp var updateResult = dbct.BulkUpdate(rows, row => new { row.Column3, row.Column2 }); Console.WriteLine($"Updated: {updateResult.AffectedRows} row(s)"); ```