CSharp · Console
// Bulk Operations
// Doc: https://bulk-operations.net/bulk-merge
// @nuget: Z.BulkOperations
// @nuget: System.Data.SqlClient
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using Z.BulkOperations;
public class Program
{
public static List<BenchmarkResult> BenchmarkResults = new List<BenchmarkResult>();
public static void Main()
{
GenerateDatabase();
JustInTime_Compile();
var customerCount = 1000;
var clockBulkMerge = new Stopwatch();
// Generate X customers (half for update, half for insert)
var dtCustomers = GenerateCustomers(customerCount);
dtCustomers.AsEnumerable().ToList().ForEach(x => x["FirstName"] += "_z");
using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServer()))
{
connection.Open();
// BulkMerge
using (var bulk = new BulkOperation(connection))
{
bulk.DestinationTableName = "Customers";
bulk.AutoMapOutputDirection = false; // performance can be improved with options
clockBulkMerge.Start();
bulk.BulkMerge(dtCustomers);
clockBulkMerge.Stop();
BenchmarkResults.Add(new BenchmarkResult() { Action = "BulkMerge (Bulk Operations)", Entities = dtCustomers.Rows.Count, Performance = clockBulkMerge.ElapsedMilliseconds + " ms" });
}
}
FiddleHelper.WriteTable(BenchmarkResults);
}
public static void JustInTime_Compile()
{
using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServer()))
{
connection.Open();
DataTable dtCustomers = new DataTable("Customers");
dtCustomers.Columns.Add("CustomerID", typeof(int));
dtCustomers.Columns.Add("Code", typeof(string));
dtCustomers.Columns.Add("FirstName", typeof(string));
dtCustomers.Columns.Add("LastName", typeof(string));
for(int i = 0; i < 20; i++)
{
var drCustomer = dtCustomers.NewRow();
drCustomer["Code"] = "Update_Code_" + i;
drCustomer["FirstName"] = "Update_FirstName_" + i;
drCustomer["LastName"] ="Update_LastName_" + i;
dtCustomers.Rows.Add(drCustomer);
}
// BulkInsert
using (var bulk = new BulkOperation(connection))
{
bulk.DestinationTableName = "Customers";
bulk.AutoMapOutputDirection = false;
bulk.BulkInsert(dtCustomers);
// Clean
bulk.BulkDelete(dtCustomers);
}
}
}
public static DataTable GenerateCustomers(int count)
{
var updateCount = count / 2;
var insertCount = count - updateCount;
DataTable dtTable = new DataTable("Customers");
dtTable.Columns.Add("CustomerID", typeof(int));
dtTable.Columns.Add("Code", typeof(string));
dtTable.Columns.Add("FirstName", typeof(string));
dtTable.Columns.Add("LastName", typeof(string));
for(int i = 0; i < updateCount; i++)
{
var drCustomer = dtTable.NewRow();
drCustomer["Code"] = "Update_Code_" + i;
drCustomer["FirstName"] = "Update_FirstName_" + i;
drCustomer["LastName"] ="Update_LastName_" + i;
dtTable.Rows.Add(drCustomer);
}
using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServer()))
{
connection.Open();
// BulkInsert
using (var bulk = new BulkOperation(connection))
{
bulk.DestinationTableName = "Customers";
bulk.BulkInsert(dtTable);
}
}
for(int i = 0; i < insertCount; i++)
{
var drCustomer = dtTable.NewRow();
drCustomer["Code"] = "Insert_Code_" + i;
drCustomer["FirstName"] = "Insert_FirstName_" + i;
drCustomer["LastName"] ="Insert_LastName_" + i;
dtTable.Rows.Add(drCustomer);
}
return dtTable;
}
public static void GenerateDatabase()
{
using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServer()))
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText = @"
CREATE TABLE [Customers]
(
[CustomerID] [INT] IDENTITY(1,1) NOT NULL,
[Code] [NVARCHAR](MAX) NULL,
[FirstName] [NVARCHAR](MAX) NULL,
[LastName] [NVARCHAR](MAX) NULL,
CONSTRAINT [PK_Customers] PRIMARY KEY CLUSTERED
(
[CustomerID] ASC
)
)
";
command.ExecuteNonQuery();
}
}
}
public class BenchmarkResult
{
public string Action { get; set; }
public int Entities { get; set; }
public string Performance { get; set; }
}
}