test
This commit is contained in:
parent
0f335617b4
commit
e9c638b155
@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ConsoleApp1.Model;
|
||||
@ -13,38 +13,14 @@ namespace ConsoleApp1.ORM
|
||||
public static void BulkInsert<TEntity>(IEnumerable<TEntity> entries)
|
||||
{
|
||||
var entityType = typeof(TEntity);
|
||||
var properties = entityType.GetProperties().Select(p => p.Name);
|
||||
BuildBulkInsertQuery(entityType.Name, properties, entries);
|
||||
var properties = entityType.GetProperties()
|
||||
.Select(p => p.Name)
|
||||
.ToArray();
|
||||
//ExecuteBulkInsertInBatches(entityType.Name, properties, entries);
|
||||
ExecuteBulkInsert(entityType.Name, properties, entries);
|
||||
}
|
||||
|
||||
private static void GetParametersValues(string tableName, IEnumerable<string> propertyNames, IEnumerable entries)
|
||||
{
|
||||
static object GetPropertyValue(object o, string propertyName)
|
||||
{
|
||||
//Debug.Assert(propertyName != null, nameof(propertyName) + " != null");
|
||||
var type = o.GetType();
|
||||
var property = type.GetProperty(propertyName);
|
||||
//Debug.Assert(property != null, nameof(property) + " != null");
|
||||
var propertyValue = property?.GetValue(o);
|
||||
return propertyValue;
|
||||
}
|
||||
|
||||
var fields = propertyNames as string[] ?? propertyNames.ToArray();
|
||||
var i = 0;
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
++i;
|
||||
Console.WriteLine($"Entry number {i}");
|
||||
foreach (var propertyName in fields)
|
||||
{
|
||||
var propertyValue = GetPropertyValue(entry, propertyName);
|
||||
Console.WriteLine($"Property name={propertyName}, value={propertyValue}");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
private static void BuildBulkInsertQuery(string tableName,
|
||||
private static void ExecuteBulkInsertInBatches(string tableName,
|
||||
IEnumerable<string> propertyNames,
|
||||
IEnumerable entries,
|
||||
int maxBatchSize = 5)
|
||||
@ -108,66 +84,54 @@ namespace ConsoleApp1.ORM
|
||||
}
|
||||
}
|
||||
|
||||
public static void BulkInsert1(IEnumerable<Person> persons)
|
||||
private static void ExecuteBulkInsert(string tableName,
|
||||
IReadOnlyCollection<string> columns,
|
||||
IEnumerable entries)
|
||||
{
|
||||
using var session = NHibernateHelper.OpenSession();
|
||||
var cmd = session.Connection.CreateCommand();
|
||||
var queryString = BuildBulkInsertQueryString(tableName, columns, entries);
|
||||
var query = session.CreateSQLQuery(queryString);
|
||||
|
||||
var queryString = "INSERT INTO Person (Id, FirstName, LastName) VALUES\n";
|
||||
var sb = new StringBuilder();
|
||||
static object GetPropertyValue(object o, string propertyName) => o.GetType().GetProperty(propertyName)?.GetValue(o);
|
||||
|
||||
var batchSize = 0;
|
||||
var p = 1; //the current paramter name (i.e. "@p1") we're going to use
|
||||
|
||||
DbParameter CreateDbParameter(object value)
|
||||
var parameterIndex = 0;
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
var pm = cmd.CreateParameter();
|
||||
pm.Value = value;
|
||||
return pm;
|
||||
}
|
||||
|
||||
foreach (var person in persons)
|
||||
foreach (var column in columns)
|
||||
{
|
||||
//Build the names of the parameters
|
||||
var pId = $"@p{p}"; //the "Id" parameter name (i.e. "p1")
|
||||
var pFirstName = $"@p{p + 1}";
|
||||
var pLastName = $"@p{p + 2}";
|
||||
p += 3;
|
||||
var value = GetPropertyValue(entry, column);
|
||||
query.SetParameter(parameterIndex, value);
|
||||
parameterIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
//Build a single "(p1, p2)" row
|
||||
var row = $"({pId}, {pFirstName}, {pLastName})"; //a single values tuple
|
||||
query.ExecuteUpdate();
|
||||
}
|
||||
|
||||
//Add the row to our running SQL batch
|
||||
if (batchSize > 0) sb.AppendLine(",");
|
||||
sb.Append(row);
|
||||
batchSize += 1;
|
||||
|
||||
// Add the parameter values for this row
|
||||
cmd.Parameters.AddRange(new[] {
|
||||
CreateDbParameter(person.Id),
|
||||
CreateDbParameter(person.FirstName),
|
||||
CreateDbParameter(person.LastName)
|
||||
});
|
||||
|
||||
if (batchSize >= 5)
|
||||
private static string BuildBulkInsertQueryString(string tableName,
|
||||
IReadOnlyCollection<string> columns,
|
||||
IEnumerable entries)
|
||||
{
|
||||
var queryStringComplete = queryString + sb;
|
||||
cmd.CommandText = queryStringComplete;
|
||||
cmd.ExecuteNonQuery();
|
||||
cmd.Parameters.Clear();
|
||||
sb.Clear();
|
||||
batchSize = 0;
|
||||
p = 1;
|
||||
}
|
||||
var queryString = $"INSERT INTO {tableName} ({string.Join(',', columns)}) VALUES";
|
||||
var sb = new StringBuilder(queryString).AppendLine();
|
||||
var e = entries.GetEnumerator();
|
||||
for (e.MoveNext();;)
|
||||
{
|
||||
sb.Append("(");
|
||||
for (var col = 0; col < columns.Count; col++)
|
||||
{
|
||||
sb.Append($"?");
|
||||
if (col < columns.Count - 1) sb.Append(",");
|
||||
}
|
||||
|
||||
//handle the last few stragglers
|
||||
if (batchSize > 0)
|
||||
if (!e.MoveNext())
|
||||
{
|
||||
var queryStringComplete = queryString + sb;
|
||||
cmd.CommandText = queryStringComplete;
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
sb.Append(");");
|
||||
break;
|
||||
}
|
||||
sb.AppendLine("),");
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@ -72,14 +72,16 @@ namespace ConsoleApp1.Repository
|
||||
[Test]
|
||||
public void TestBulkInsert()
|
||||
{
|
||||
static IEnumerable<Person> GeneratePersons(int num = 3)
|
||||
static Person[] GeneratePersons(int num = 3)
|
||||
{
|
||||
var ret = new Person[num];
|
||||
for (var ii = 0; ii < num; ii++) ret[ii] = new Person {Id = Guid.NewGuid(), FirstName = "bac", LastName = "fif"};
|
||||
return ret;
|
||||
}
|
||||
|
||||
_personRepo.Save(GeneratePersons(10));
|
||||
var persons = GeneratePersons(10000);
|
||||
_personRepo.Save(persons);
|
||||
Assert.AreEqual(10000, _personRepo.RowCount());
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
|
Reference in New Issue
Block a user