first commit
This commit is contained in:
commit
0f335617b4
16
ConsoleApp1.sln
Normal file
16
ConsoleApp1.sln
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp1", "ConsoleApp1\ConsoleApp1.csproj", "{C1AF7B05-8631-49ED-88F5-946446E9169F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C1AF7B05-8631-49ED-88F5-946446E9169F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C1AF7B05-8631-49ED-88F5-946446E9169F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C1AF7B05-8631-49ED-88F5-946446E9169F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C1AF7B05-8631-49ED-88F5-946446E9169F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
13
ConsoleApp1/Model/Person.cs
Normal file
13
ConsoleApp1/Model/Person.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace ConsoleApp1.Model
|
||||
{
|
||||
public class Person
|
||||
{
|
||||
public virtual Guid Id { get; set; }
|
||||
public virtual string FirstName { get; set; }
|
||||
public virtual string LastName { get; set; }
|
||||
|
||||
public virtual string GetFullName() => $"{FirstName} {LastName}";
|
||||
}
|
||||
}
|
15
ConsoleApp1/Model/PersonMap.cs
Normal file
15
ConsoleApp1/Model/PersonMap.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using NHibernate.Mapping.ByCode;
|
||||
using NHibernate.Mapping.ByCode.Conformist;
|
||||
|
||||
namespace ConsoleApp1.Model
|
||||
{
|
||||
public class PersonMap : ClassMapping<Person>
|
||||
{
|
||||
public PersonMap()
|
||||
{
|
||||
Id(x => x.Id, m => m.Generator(Generators.GuidComb));
|
||||
Property(x => x.FirstName);
|
||||
Property(x => x.LastName);
|
||||
}
|
||||
}
|
||||
}
|
23
ConsoleApp1/Model/PersonMapTest.cs
Normal file
23
ConsoleApp1/Model/PersonMapTest.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Xml.Serialization;
|
||||
using NHibernate.Mapping.ByCode;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace ConsoleApp1.Model
|
||||
{
|
||||
[TestFixture]
|
||||
public class PersonMapTest
|
||||
{
|
||||
[Test]
|
||||
public void CanGenerateXmlMapping()
|
||||
{
|
||||
var mapper = new ModelMapper();
|
||||
mapper.AddMapping<PersonMap>();
|
||||
|
||||
var mapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
|
||||
var xmlSerializer = new XmlSerializer(mapping.GetType());
|
||||
|
||||
xmlSerializer.Serialize(Console.Out, mapping);
|
||||
}
|
||||
}
|
||||
}
|
23
ConsoleApp1/Model/PersonTest.cs
Normal file
23
ConsoleApp1/Model/PersonTest.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace ConsoleApp1.Model
|
||||
{
|
||||
[TestFixture]
|
||||
public class PersonTest
|
||||
{
|
||||
[Test]
|
||||
public void GetFullNameTest()
|
||||
{
|
||||
var person = new Person
|
||||
{
|
||||
FirstName = "Test",
|
||||
LastName = "Kees"
|
||||
};
|
||||
|
||||
Assert.AreEqual("Test", person.FirstName);
|
||||
Assert.AreEqual("Kees", person.LastName);
|
||||
|
||||
Assert.AreEqual("Test Kees", person.GetFullName());
|
||||
}
|
||||
}
|
||||
}
|
173
ConsoleApp1/ORM/BulkQuery.cs
Normal file
173
ConsoleApp1/ORM/BulkQuery.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
48
ConsoleApp1/ORM/NHibernateHelper.cs
Normal file
48
ConsoleApp1/ORM/NHibernateHelper.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
17
ConsoleApp1/ORM/SchemaTest.cs
Normal file
17
ConsoleApp1/ORM/SchemaTest.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
87
ConsoleApp1/Repository/PersonRepository.cs
Normal file
87
ConsoleApp1/Repository/PersonRepository.cs
Normal file
@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ConsoleApp1.Model;
|
||||
using ConsoleApp1.ORM;
|
||||
|
||||
namespace ConsoleApp1.Repository
|
||||
{
|
||||
public interface PersonRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// Get person entity by id
|
||||
/// </summary>
|
||||
/// <param name="id">id</param>
|
||||
/// <returns>person</returns>
|
||||
Person Get(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// Save person entity
|
||||
/// </summary>
|
||||
/// <param name="person">person</param>
|
||||
void Save(Person person);
|
||||
|
||||
/// <summary>
|
||||
/// Update person entity
|
||||
/// </summary>
|
||||
/// <param name="person">person</param>
|
||||
void Update(Person person);
|
||||
|
||||
/// <summary>
|
||||
/// Delete person entity
|
||||
/// </summary>
|
||||
/// <param name="person">person</param>
|
||||
void Delete(Person person);
|
||||
|
||||
/// <summary>
|
||||
/// Row count person in db
|
||||
/// </summary>
|
||||
/// <returns>number of rows</returns>
|
||||
long RowCount();
|
||||
|
||||
void Save(IEnumerable<Person> persons);
|
||||
}
|
||||
|
||||
public class PersonRepositoryNHibernate : PersonRepository
|
||||
{
|
||||
public void Save(IEnumerable<Person> persons)
|
||||
{
|
||||
BulkQuery.BulkInsert(persons);
|
||||
}
|
||||
|
||||
public void Save(Person person)
|
||||
{
|
||||
using var session = NHibernateHelper.OpenSession();
|
||||
using var transaction = session.BeginTransaction();
|
||||
session.Save(person);
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
public Person Get(Guid id)
|
||||
{
|
||||
using var session = NHibernateHelper.OpenSession();
|
||||
return session.Get<Person>(id);
|
||||
}
|
||||
|
||||
public void Update(Person person)
|
||||
{
|
||||
using var session = NHibernateHelper.OpenSession();
|
||||
using var transaction = session.BeginTransaction();
|
||||
session.Update(person);
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
public void Delete(Person person)
|
||||
{
|
||||
using var session = NHibernateHelper.OpenSession();
|
||||
using var transaction = session.BeginTransaction();
|
||||
session.Delete(person);
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
public long RowCount()
|
||||
{
|
||||
using var session = NHibernateHelper.OpenSession();
|
||||
return session.QueryOver<Person>().RowCountInt64();
|
||||
}
|
||||
}
|
||||
}
|
92
ConsoleApp1/Repository/PersonRepositoryTest.cs
Normal file
92
ConsoleApp1/Repository/PersonRepositoryTest.cs
Normal file
@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
using ConsoleApp1.Model;
|
||||
using ConsoleApp1.ORM;
|
||||
using NHibernate.Tool.hbm2ddl;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace ConsoleApp1.Repository
|
||||
{
|
||||
[TestFixture]
|
||||
public class NHibernatePersonRepositoryTest
|
||||
{
|
||||
private PersonRepository _personRepo;
|
||||
|
||||
[SetUp]
|
||||
public void CreateSchema()
|
||||
{
|
||||
DeleteDatabaseIfExists();
|
||||
|
||||
var schemaUpdate = new SchemaUpdate(NHibernateHelper.Configuration);
|
||||
schemaUpdate.Execute(false, true);
|
||||
|
||||
_personRepo = new PersonRepositoryNHibernate();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanSavePerson()
|
||||
{
|
||||
_personRepo.Save(new Person());
|
||||
Assert.AreEqual(1, _personRepo.RowCount());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanGetPerson()
|
||||
{
|
||||
var person = new Person();
|
||||
_personRepo.Save(person);
|
||||
Assert.AreEqual(1, _personRepo.RowCount());
|
||||
|
||||
person = _personRepo.Get(person.Id);
|
||||
Assert.IsNotNull(person);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanUpdatePerson()
|
||||
{
|
||||
var person = new Person();
|
||||
_personRepo.Save(person);
|
||||
Assert.AreEqual(1, _personRepo.RowCount());
|
||||
|
||||
person = _personRepo.Get(person.Id);
|
||||
person.FirstName = "Test";
|
||||
_personRepo.Update(person);
|
||||
|
||||
Assert.AreEqual(1, _personRepo.RowCount());
|
||||
Assert.AreEqual("Test", _personRepo.Get(person.Id).FirstName);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanDeletePerson()
|
||||
{
|
||||
var person = new Person();
|
||||
_personRepo.Save(person);
|
||||
Assert.AreEqual(1, _personRepo.RowCount());
|
||||
|
||||
_personRepo.Delete(person);
|
||||
Assert.AreEqual(0, _personRepo.RowCount());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBulkInsert()
|
||||
{
|
||||
static IEnumerable<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));
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void DeleteDatabaseIfExists()
|
||||
{
|
||||
if (File.Exists("test.db"))
|
||||
File.Delete("test.db");
|
||||
}
|
||||
}
|
||||
}
|
9
ConsoleApp1/hibernate.cfg.xml
Normal file
9
ConsoleApp1/hibernate.cfg.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
|
||||
<session-factory name="NHibernate.Test">
|
||||
<property name="connection.driver_class">NHibernate.Driver.SQLite20Driver</property>
|
||||
<property name="connection.connection_string">Data Source=test.db;Version=3;New=True</property>
|
||||
<property name="dialect">NHibernate.Dialect.SQLiteDialect</property>
|
||||
<property name="show_sql">true</property>
|
||||
</session-factory>
|
||||
</hibernate-configuration>
|
@ -0,0 +1,4 @@
|
||||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v3.1", FrameworkDisplayName = "")]
|
@ -0,0 +1,22 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: System.Reflection.AssemblyCompanyAttribute("ConsoleApp1")]
|
||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("ConsoleApp1")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("ConsoleApp1")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
// Généré par la classe MSBuild WriteCodeFragment.
|
||||
|
Reference in New Issue
Block a user