first commit

This commit is contained in:
2020-06-09 00:12:01 +02:00
commit 0f335617b4
13 changed files with 542 additions and 0 deletions

View File

@ -0,0 +1,173 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
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);
var properties = entityType.GetProperties().Select(p => p.Name);
BuildBulkInsertQuery(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,
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();
}
}
public static void BulkInsert1(IEnumerable<Person> persons)
{
using var session = NHibernateHelper.OpenSession();
var cmd = session.Connection.CreateCommand();
var queryString = "INSERT INTO Person (Id, FirstName, LastName) VALUES\n";
var sb = new StringBuilder();
var batchSize = 0;
var p = 1; //the current paramter name (i.e. "@p1") we're going to use
DbParameter CreateDbParameter(object value)
{
var pm = cmd.CreateParameter();
pm.Value = value;
return pm;
}
foreach (var person in persons)
{
//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;
//Build a single "(p1, p2)" row
var row = $"({pId}, {pFirstName}, {pLastName})"; //a single values tuple
//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)
{
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();
}
}
}
}

View File

@ -0,0 +1,48 @@
using System.Collections.Generic;
using ConsoleApp1.Model;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Mapping.ByCode;
namespace ConsoleApp1.ORM
{
public static class NHibernateHelper
{
private static ISessionFactory _sessionFactory;
private static Configuration _configuration;
private static HbmMapping _mapping;
public static ISession OpenSession()
{
//Open and return the nhibernate session
return SessionFactory.OpenSession();
}
public static ISessionFactory SessionFactory => _sessionFactory ??= Configuration.BuildSessionFactory();
public static Configuration Configuration => _configuration ??= CreateConfiguration();
public static HbmMapping Mapping => _mapping ??= CreateMapping();
private static Configuration CreateConfiguration()
{
var configuration = new Configuration();
//Loads properties from hibernate.cfg.xml
configuration.Configure();
//Loads nhibernate mappings
configuration.AddDeserializedMapping(Mapping, null);
return configuration;
}
private static HbmMapping CreateMapping()
{
var mapper = new ModelMapper();
//Add the person mapping to the model mapper
mapper.AddMappings(new List<System.Type> { typeof(PersonMap) });
//Create and return a HbmMapping of the model mapping in code
return mapper.CompileMappingForAllExplicitlyAddedEntities();
}
}
}

View File

@ -0,0 +1,17 @@
using System;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;
namespace ConsoleApp1.ORM
{
[TestFixture]
public class SchemaTest
{
[Test]
public void CanGenerateSchema()
{
var schemaUpdate = new SchemaUpdate(NHibernateHelper.Configuration);
schemaUpdate.Execute(Console.WriteLine, true);
}
}
}