2020-06-08 22:12:01 +00:00
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Data.Common;
|
2020-06-09 19:10:20 +00:00
|
|
|
using System.Diagnostics;
|
2020-06-08 22:12:01 +00:00
|
|
|
using System.Linq;
|
|
|
|
using System.Text;
|
|
|
|
using ConsoleApp1.Model;
|
|
|
|
|
|
|
|
namespace ConsoleApp1.ORM
|
|
|
|
{
|
|
|
|
public class BulkQuery
|
|
|
|
{
|
|
|
|
public static void BulkInsert<TEntity>(IEnumerable<TEntity> entries)
|
|
|
|
{
|
|
|
|
var entityType = typeof(TEntity);
|
2020-06-09 19:10:20 +00:00
|
|
|
var properties = entityType.GetProperties()
|
|
|
|
.Select(p => p.Name)
|
|
|
|
.ToArray();
|
|
|
|
//ExecuteBulkInsertInBatches(entityType.Name, properties, entries);
|
|
|
|
ExecuteBulkInsert(entityType.Name, properties, entries);
|
2020-06-08 22:12:01 +00:00
|
|
|
}
|
|
|
|
|
2020-06-09 19:10:20 +00:00
|
|
|
private static void ExecuteBulkInsertInBatches(string tableName,
|
2020-06-08 22:12:01 +00:00
|
|
|
IEnumerable<string> propertyNames,
|
|
|
|
IEnumerable entries,
|
|
|
|
int maxBatchSize = 5)
|
|
|
|
{
|
|
|
|
using var session = NHibernateHelper.OpenSession();
|
|
|
|
var cmd = session.Connection.CreateCommand();
|
|
|
|
var columns = propertyNames as string[] ?? propertyNames.ToArray();
|
|
|
|
var queryString = $"INSERT INTO {tableName} ({string.Join(',', columns)}) VALUES\n";
|
|
|
|
var sb = new StringBuilder();
|
|
|
|
|
|
|
|
DbParameter CreateDbParameter(object value)
|
|
|
|
{
|
|
|
|
var pm = cmd.CreateParameter();
|
|
|
|
pm.Value = value;
|
|
|
|
return pm;
|
|
|
|
}
|
|
|
|
|
|
|
|
static object GetPropertyValue(object o, string propertyName) => o.GetType().GetProperty(propertyName)?.GetValue(o);
|
|
|
|
|
|
|
|
var batchSize = 0;
|
|
|
|
var p = 0;
|
|
|
|
foreach (var entry in entries)
|
|
|
|
{
|
|
|
|
// Build the names of the parameters
|
|
|
|
var row = new StringBuilder("(");
|
|
|
|
for (var ii = 0; ii < columns.Length; ii++)
|
|
|
|
{
|
|
|
|
row.Append($"@p{p + ii}");
|
|
|
|
if (ii < columns.Length - 1) row.Append(",");
|
|
|
|
|
|
|
|
// Set parameter value
|
|
|
|
var value = GetPropertyValue(entry, columns[ii]);
|
|
|
|
cmd.Parameters.Add(CreateDbParameter(value));
|
|
|
|
}
|
|
|
|
p += columns.Length;
|
|
|
|
row.Append(")");
|
|
|
|
|
|
|
|
// Add the row to our running SQL batch
|
|
|
|
if (batchSize > 0) sb.AppendLine(",");
|
|
|
|
sb.Append(row);
|
|
|
|
batchSize += 1;
|
|
|
|
|
|
|
|
if (batchSize >= maxBatchSize)
|
|
|
|
{
|
|
|
|
var queryStringComplete = queryString + sb + ";";
|
|
|
|
cmd.CommandText = queryStringComplete;
|
|
|
|
cmd.ExecuteNonQuery();
|
|
|
|
cmd.Parameters.Clear();
|
|
|
|
sb.Clear();
|
|
|
|
batchSize = 0;
|
|
|
|
p = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// handle the last few stragglers
|
|
|
|
if (batchSize > 0)
|
|
|
|
{
|
|
|
|
var queryStringComplete = queryString + sb + ";";
|
|
|
|
cmd.CommandText = queryStringComplete;
|
|
|
|
cmd.ExecuteNonQuery();
|
|
|
|
}
|
|
|
|
}
|
2020-06-09 19:10:20 +00:00
|
|
|
|
|
|
|
private static void ExecuteBulkInsert(string tableName,
|
|
|
|
IReadOnlyCollection<string> columns,
|
|
|
|
IEnumerable entries)
|
2020-06-08 22:12:01 +00:00
|
|
|
{
|
|
|
|
using var session = NHibernateHelper.OpenSession();
|
2020-06-09 19:10:20 +00:00
|
|
|
var queryString = BuildBulkInsertQueryString(tableName, columns, entries);
|
|
|
|
var query = session.CreateSQLQuery(queryString);
|
|
|
|
|
|
|
|
static object GetPropertyValue(object o, string propertyName) => o.GetType().GetProperty(propertyName)?.GetValue(o);
|
|
|
|
|
|
|
|
var parameterIndex = 0;
|
|
|
|
foreach (var entry in entries)
|
2020-06-08 22:12:01 +00:00
|
|
|
{
|
2020-06-09 19:10:20 +00:00
|
|
|
foreach (var column in columns)
|
|
|
|
{
|
|
|
|
var value = GetPropertyValue(entry, column);
|
|
|
|
query.SetParameter(parameterIndex, value);
|
|
|
|
parameterIndex++;
|
|
|
|
}
|
2020-06-08 22:12:01 +00:00
|
|
|
}
|
|
|
|
|
2020-06-09 19:10:20 +00:00
|
|
|
query.ExecuteUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
private static string BuildBulkInsertQueryString(string tableName,
|
|
|
|
IReadOnlyCollection<string> columns,
|
|
|
|
IEnumerable entries)
|
|
|
|
{
|
|
|
|
var queryString = $"INSERT INTO {tableName} ({string.Join(',', columns)}) VALUES";
|
|
|
|
var sb = new StringBuilder(queryString).AppendLine();
|
|
|
|
var e = entries.GetEnumerator();
|
|
|
|
for (e.MoveNext();;)
|
2020-06-08 22:12:01 +00:00
|
|
|
{
|
2020-06-09 19:10:20 +00:00
|
|
|
sb.Append("(");
|
|
|
|
for (var col = 0; col < columns.Count; col++)
|
2020-06-08 22:12:01 +00:00
|
|
|
{
|
2020-06-09 19:10:20 +00:00
|
|
|
sb.Append($"?");
|
|
|
|
if (col < columns.Count - 1) sb.Append(",");
|
2020-06-08 22:12:01 +00:00
|
|
|
}
|
2020-06-09 19:10:20 +00:00
|
|
|
|
|
|
|
if (!e.MoveNext())
|
|
|
|
{
|
|
|
|
sb.Append(");");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
sb.AppendLine("),");
|
2020-06-08 22:12:01 +00:00
|
|
|
}
|
2020-06-09 19:10:20 +00:00
|
|
|
return sb.ToString();
|
2020-06-08 22:12:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|