Skip to content

Entity database persistence

Martin Havlišta edited this page Jul 11, 2018 · 20 revisions

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:

  1. Add CoreDdd.Nhibernate package into the project.
  2. Create a new NHibernate configurator class derived from NhibernateConfigurator to configure NHibernate and to let it know where to look for entities for persistence:
    public class CoreDddSampleNhibernateConfigurator : NhibernateConfigurator
    {
        protected override Assembly[] GetAssembliesToMap()
        {
            return new[] { typeof(Ship).Assembly };
        }
    }
  1. 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>

  </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>

  </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>

  </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).

  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.

  2. Add a method to create a database, SQLite example:

        private static void _CreateDatabase(INhibernateConfigurator nhibernateConfigurator)
        {
            var configuration = nhibernateConfigurator.GetConfiguration();
            var connectionString = configuration.Properties["connection.connection_string"];

            using (var connection = new SQLiteConnection(connectionString))
            {
                connection.Open();
                new SchemaExport(configuration).Execute(
                        useStdOut: true,
                        execute: true,
                        justDrop: false,
                        connection: connection,
                        exportOutput: Console.Out)
                    ;
            }
        }

You can replace SQLiteConnection by SqlConnection for SQL Server or NpgsqlConnection for PostgreSQL. This 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.

  1. 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);

                    unitOfWork.Commit();

                    Console.WriteLine("Ship entity was persisted.");
                }
                catch
                {
                    unitOfWork.Rollback();
                    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.

Clone this wiki locally