Bulk Operations - BulkMerge - Performance Comparison (Entity) (NET Core)

CSharp · Console

/Program.cs

// Bulk Operations
// Doc: https://bulk-operations.net/bulk-merge 

// @nuget: Z.BulkOperations
// @nuget: System.Data.SqlClient

using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using System.Data;
using System.Data.SqlClient;
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 customers = GenerateCustomers(customerCount);
		customers.ForEach(x => x.FirstName += "_z");
		
		using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServer()))
		{		
			connection.Open();
			
			// BulkMerge 
			using (var bulk = new BulkOperation<Customer>(connection))
			{
				bulk.DestinationTableName = "Customers";
								
				clockBulkMerge.Start();
				bulk.BulkMerge(customers); 
				clockBulkMerge.Stop();
								
				BenchmarkResults.Add(new BenchmarkResult() { Action = "BulkMerge (Bulk Operations)", Entities = customers.Count(), Performance = clockBulkMerge.ElapsedMilliseconds + " ms" });
			}
		}
		
		FiddleHelper.WriteTable(BenchmarkResults);
	}
		 
	public static void JustInTime_Compile()
	{
		using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServer()))
		{
			var list = new List<Customer>();

			for(int i = 0; i < 20; i++)
			{
				list.Add(new Customer() { Code = "Update_Code_" + i, FirstName = "Update_FirstName_" + i, LastName = "Update_LastName_" + i });
			}
			
			connection.Open();
			
			// BulkMerge
			using (var bulk = new BulkOperation<Customer>(connection))
			{
				bulk.DestinationTableName = "Customers";
				
				bulk.BulkMerge(list);
				
				// Clean
				bulk.BulkDelete(list);
			}
		}
	}
	
	public static List<Customer> GenerateCustomers(int count)
	{
		var updateCount = count / 2;
		var insertCount = count - updateCount;
		
		var list = new List<Customer>();
		
		for(int i = 0; i < updateCount; i++)
		{
			list.Add(new Customer() { Code = "Update_Code_" + i, FirstName = "Update_FirstName_" + i, LastName = "Update_LastName_" + i });
		}
		
		using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServer()))
		{		
			connection.Open();
			
			// BulkInsert
			using (var bulk = new BulkOperation<Customer>(connection))
			{
				bulk.DestinationTableName = "Customers";
				// BulkInsert
				bulk.BulkInsert(list); 
			}
		}
		

		for(int i = 0; i < insertCount; i++)
		{
			list.Add(new Customer() { Code = "Insert_Code_" + i, FirstName = "Insert_FirstName_" + i, LastName = "Insert_LastName_" + i });
		}
		
		return list;
	}

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 Customer
	{
		public int CustomerID { get; set; }
		public string Code { get; set; }
		public string FirstName { get; set; }
		public string LastName { get; set; }
	}
	
	public class BenchmarkResult
	{
		public string Action { get; set; }
		public int Entities { get; set; }
		public string Performance { get; set; }
	}
}
;