-
Notifications
You must be signed in to change notification settings - Fork 6
Entity database persistence
To persist an entity, for example a Ship
entity:
public class Ship : Entity, IAggregateRoot
{
protected Ship() { } // parameterless constructor needed by nhibernate
// to be able to instantiate the entity when loaded from database
public Ship(string name, decimal tonnage)
{
Name = name;
Tonnage = tonnage;
}
public virtual string Name { get; protected set; } // virtual modifier needed by nhibernate
// - https://stackoverflow.com/a/848116/379279
public virtual decimal Tonnage { get; protected set; } // protected modifier needed by nhibernate
}
into a database, follow these steps:
- Add CoreDdd.Nhibernate package into the project.
- Create a new NHibernate configurator class derived from
BaseNhibernateConfigurator
to configure NHibernate and to let it know where to look for entities for persistence:
public class CoreDddSampleNhibernateConfigurator : BaseNhibernateConfigurator
{
protected override Assembly[] GetAssembliesToMap()
{
return new[] { typeof(Ship).Assembly };
}
}
- Add a new file
hibernate.cfg.xml
into the project to configure which database to persist the entities into.
SQLite example:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.connection_string">Data Source=CoreDddSampleConsoleApp.db</property>
<property name="dialect">NHibernate.Dialect.SQLiteDialect</property>
<property name="connection.driver_class">NHibernate.Driver.SQLite20Driver</property>
<property name="connection.release_mode">on_close</property>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="show_sql">false</property>
<property name="proxyfactory.factory_class">NHibernate.Bytecode.DefaultProxyFactoryFactory, NHibernate</property>
<property name="transaction.use_connection_on_system_prepare">false</property> <!-- set transaction.use_connection_on_system_prepare to 'false' when using .NET 4.6.1+ or .NET Standard 2.0+, NHibernate 5.1.0+, more info here https://github.com/npgsql/npgsql/issues/1985#issuecomment-397266128 ; remove this line for previous NHibernate versions -->
</session-factory>
</hibernate-configuration>
SQL server example:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.connection_string">Server=<server name>; User=<user name>;Password=<password>;Initial Catalog=CoreDddSampleConsoleApp;</property>
<property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="show_sql">false</property>
<property name="proxyfactory.factory_class">NHibernate.Bytecode.DefaultProxyFactoryFactory, NHibernate</property>
<property name="transaction.use_connection_on_system_prepare">false</property> <!-- set transaction.use_connection_on_system_prepare to 'false' when using .NET 4.6.1+ or .NET Standard 2.0+, NHibernate 5.1.0+, more info here https://github.com/npgsql/npgsql/issues/1985#issuecomment-397266128 ; remove this line for previous NHibernate versions -->
</session-factory>
</hibernate-configuration>
PostgreSQL example:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.connection_string">Server=<server name>;Port=5432;Database=CoreDddSampleConsoleApp;User Id=<user name>;Password=<password>;Enlist=true</property>
<property name="dialect">NHibernate.Dialect.PostgreSQL82Dialect</property>
<property name="connection.driver_class">NHibernate.Driver.NpgsqlDriver</property>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="show_sql">false</property>
<property name="proxyfactory.factory_class">NHibernate.Bytecode.DefaultProxyFactoryFactory, NHibernate</property>
<property name="transaction.use_connection_on_system_prepare">false</property> <!-- set transaction.use_connection_on_system_prepare to 'false' when using .NET 4.6.1+ or .NET Standard 2.0+, NHibernate 5.1.0+, more info here https://github.com/npgsql/npgsql/issues/1985#issuecomment-397266128 ; remove this line for previous NHibernate versions -->
</session-factory>
</hibernate-configuration>
In hibernate.cfg.xml
properties, set 'Build Action' to 'Content' and 'Copy to Output Directory' to 'Copy if newer' - this will copy hibernate.cfg.xml
into the build output folder (e.g. bin\Debug\netcoreapp2.1).
-
Add your data provider package into the project, e.g. System.Data.SQLite.Core for SQLite, System.Data.SqlClient for SQL Server, Npgsql for PostgreSQL.
-
To persist an entity into a database, the database needs to be created first. Use the following code sample to create a database, SQLite example:
var nhibernateConfigurator = new CoreDddSampleNhibernateConfigurator();
var configuration = nhibernateConfigurator.GetConfiguration();
var connectionString = configuration.Properties["connection.connection_string"];
using (var connection = new SQLiteConnection(connectionString))
{
connection.Open();
await new SchemaExport(configuration).ExecuteAsync(
useStdOut: true,
execute: true,
justDrop: false,
connection: connection,
exportOutput: null
);
}
You can replace SQLiteConnection
by SqlConnection
for SQL Server or NpgsqlConnection
for PostgreSQL. This code sample uses NHibernate SchemaExport
feature which is able to generate SQL create database script from the domain entities code and execute it against the database.
- Persist a
Ship
entity using the following code:
using (var unitOfWork = new NhibernateUnitOfWork(nhibernateConfigurator))
{
unitOfWork.BeginTransaction();
var shipRepository = new NhibernateRepository<Ship>(unitOfWork);
try
{
var ship = new Ship("ship name", tonnage: 10m);
await shipRepository.SaveAsync(ship);
await unitOfWork.CommitAsync();
Console.WriteLine("Ship entity was persisted.");
}
catch
{
await unitOfWork.RollbackAsync();
throw;
}
}
This code sample uses CoreDdd NhibernateUnitOfWork which is a transactional wrapper around NHibernate session. The entity persistence sample above is available here as .NET Core console app.