using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Threading.Tasks;
using System.Diagnostics;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
public static List<BenchmarkResult> BenchmarkResults = new List<BenchmarkResult>();
public static async Task Main()
var customers = GenerateCustomers(1000);
await JustInTime_Compile(customers);
using (var context = new EntityContext())
context.Customers.AddRange(customers);
await context.SaveChangesAsync();
var customerIds = customers.Select(c => c.CustomerID).ToList();
var oneCustomer = customerIds.Take(1).ToList();
var tenCustomers = customerIds.Take(10).ToList();
var oneHundredCustomers = customerIds.Take(100).ToList();
var fiveHundredCustomers = customerIds.Take(500).ToList();
var oneThousandCustomers = customerIds.Take(1000).ToList();
using (var context = new EntityContext())
var sw = Stopwatch.StartNew();
var result = await PerformRead(context, oneCustomer);
BenchmarkResults.Add(new BenchmarkResult()
{Action = "Read", Entities = result.Count, Performance = sw.ElapsedMilliseconds + " ms"});
using (var context = new EntityContext())
var sw = Stopwatch.StartNew();
var result = await PerformRead(context, tenCustomers);
BenchmarkResults.Add(new BenchmarkResult()
{Action = "Read", Entities = result.Count, Performance = sw.ElapsedMilliseconds + " ms"});
using (var context = new EntityContext())
var sw = Stopwatch.StartNew();
var result = await PerformRead(context, oneHundredCustomers);
BenchmarkResults.Add(new BenchmarkResult()
{Action = "Read", Entities = result.Count, Performance = sw.ElapsedMilliseconds + " ms"});
using (var context = new EntityContext())
var sw = Stopwatch.StartNew();
var result = await PerformRead(context, fiveHundredCustomers);
BenchmarkResults.Add(new BenchmarkResult()
{Action = "Read", Entities = result.Count, Performance = sw.ElapsedMilliseconds + " ms"});
using (var context = new EntityContext())
var sw = Stopwatch.StartNew();
var result = await PerformRead(context, oneThousandCustomers);
BenchmarkResults.Add(new BenchmarkResult()
{Action = "Read", Entities = result.Count, Performance = sw.ElapsedMilliseconds + " ms"});
using (var context = new EntityContext())
var sw = Stopwatch.StartNew();
var result = await PerformTempTableRead(context, oneCustomer);
BenchmarkResults.Add(new BenchmarkResult()
{Action = "Temporary Table", Entities = result.Count, Performance = sw.ElapsedMilliseconds + " ms"});
using (var context = new EntityContext())
var sw = Stopwatch.StartNew();
var result = await PerformTempTableRead(context, tenCustomers);
BenchmarkResults.Add(new BenchmarkResult()
{Action = "Temporary Table", Entities = result.Count, Performance = sw.ElapsedMilliseconds + " ms"});
using (var context = new EntityContext())
var sw = Stopwatch.StartNew();
var result = await PerformTempTableRead(context, oneHundredCustomers);
BenchmarkResults.Add(new BenchmarkResult()
{Action = "Temporary Table", Entities = result.Count, Performance = sw.ElapsedMilliseconds + " ms"});
using (var context = new EntityContext())
var sw = Stopwatch.StartNew();
var result = await PerformTempTableRead(context, fiveHundredCustomers);
BenchmarkResults.Add(new BenchmarkResult()
{Action = "Temporary Table", Entities = result.Count, Performance = sw.ElapsedMilliseconds + " ms"});
using (var context = new EntityContext())
var sw = Stopwatch.StartNew();
var result = await PerformTempTableRead(context, oneThousandCustomers);
BenchmarkResults.Add(new BenchmarkResult()
{Action = "Temporary Table", Entities = result.Count, Performance = sw.ElapsedMilliseconds + " ms"});
using (var context = new EntityContext())
var sw = Stopwatch.StartNew();
var result = await PerformCollectionParameterRead(context, oneCustomer);
BenchmarkResults.Add(new BenchmarkResult()
{Action = "Collection Parameters", Entities = result.Count, Performance = sw.ElapsedMilliseconds + " ms"});
using (var context = new EntityContext())
var sw = Stopwatch.StartNew();
var result = await PerformCollectionParameterRead(context, tenCustomers);
BenchmarkResults.Add(new BenchmarkResult()
{Action = "Collection Parameters", Entities = result.Count, Performance = sw.ElapsedMilliseconds + " ms"});
using (var context = new EntityContext())
var sw = Stopwatch.StartNew();
var result = await PerformCollectionParameterRead(context, oneHundredCustomers);
BenchmarkResults.Add(new BenchmarkResult()
{Action = "Collection Parameters", Entities = result.Count, Performance = sw.ElapsedMilliseconds + " ms"});
using (var context = new EntityContext())
var sw = Stopwatch.StartNew();
var result = await PerformCollectionParameterRead(context, fiveHundredCustomers);
BenchmarkResults.Add(new BenchmarkResult()
{Action = "Collection Parameters", Entities = result.Count, Performance = sw.ElapsedMilliseconds + " ms"});
using (var context = new EntityContext())
var sw = Stopwatch.StartNew();
var result = await PerformCollectionParameterRead(context, oneThousandCustomers);
BenchmarkResults.Add(new BenchmarkResult()
{Action = "Collection Parameters", Entities = result.Count, Performance = sw.ElapsedMilliseconds + " ms"});
FiddleHelper.WriteTable(BenchmarkResults);
public static async Task JustInTime_Compile(List<Customer> customers)
customers = customers.Take(25).ToList();
var customerIds = customers.Select(c => c.CustomerID).ToList();
using (var context = new EntityContext())
await PerformRead(context, customerIds);
using (var context = new EntityContext())
await PerformTempTableRead(context, customerIds);
using (var context = new EntityContext())
await PerformCollectionParameterRead(context, customerIds);
public static async Task<List<Customer>> PerformRead(EntityContext context, List<int> customerIds)
return await context.Customers.Where(c => customerIds.Contains(c.CustomerID)).ToListAsync();
public static async Task<List<Customer>> PerformTempTableRead(EntityContext context, List<int> customerIds)
var tempTableQuery = (await context.BulkInsertValuesIntoTempTableAsync(customerIds)).Query;
return await context.Customers.Where(c => tempTableQuery.Contains(c.CustomerID)).ToListAsync();
public static Task<List<Customer>> PerformCollectionParameterRead(EntityContext context, List<int> customerIds)
var idsQuery = context.CreateScalarCollectionParameter(customerIds);
return context.Customers.Where(c => idsQuery.Contains(c.CustomerID)).ToListAsync();
public static List<Customer> GenerateCustomers(int count)
var list = new List<Customer>();
for (int i = 0; i < count; i++)
{Name = "Customer_" + i, Description = "Description_" + i, IsActive = i % 2 == 0});
public class EntityContext : DbContext
using (var context = new EntityContext())
context.Database.EnsureCreated();
public DbSet<Customer> Customers { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
optionsBuilder.UseSqlServer(new SqlConnection(FiddleHelper.GetConnectionStringSqlServer()), providerOptions => providerOptions.AddBulkOperationSupport().AddCollectionParameterSupport());
base.OnConfiguring(optionsBuilder);
public int CustomerID { get; set; }
public bool IsActive { get; set; }
public string Description { get; set; }
public string Name { get; set; }
public class BenchmarkResult
public string Action { get; set; }
public int Entities { get; set; }
public string Performance { get; set; }