Guidance for using NHibernate in CQRS applications.

NHibernate Module

Assembly: Lokad.Cqrs.NHibernate.dll

Lokad.CQRS Application Blocks include self-contained NHibernate Module, that could be plugged into the App Engine. This module packages:
  • Core NHibernate Assemblies
  • Fluent NHibernate
  • LINQ for NHibernate
  • Session management wiring.

Guidance

Details

In order to use NHibernate module, make sure your CQRS project references Lokad.Cqrs.NHibernate.dll. Then configure the builder using one of the snippets below.

This will register ISessionFactory and ISession in such a way, that all message handlers and scheduled tasks will use implicit unit of work matching their transaction scope and lifecycle.

In other words, you can write your code like this:

public class UpdateStatusHandler : IConsume<UpdateStatusCommand>
{
  readonly ISession _session;

  public UpdateStatusHandler(ISession session)
  {
    _session = session;
  }

  public void Consume(UpdateStatusCommand command)
  {
    var solution = session.Load<SolutionEntity>(command.SolutionId);
    solution.State = SolutionEntityState.Ready;
  }
}

New session will be provisioned for this handler, while saving all changes at the end of the processing.

Configuration

If you have connection string defined in your config file, you can use something like this:
static Configuration BuildNHibernateConfig(string connection)
{
  return Fluently
    .Configure()
    .Database(MsSqlConfiguration.MsSql2008.ConnectionString(connection))
    .Mappings(m => m.FluentMappings.AddFromAssemblyOf<SolutionEntity>())
    .BuildConfiguration();
}

builder.WithNHibernate("SqlConnection", BuildNHibernateConfig);

See FluentNHibernate Wiki for more details on writing fluent database configurations for NHibernate.

Alternatively, you can use an override that does not need connection string:
Configuration config = ...;

builder.WithNHibernate(config);

Advanced

Basically NHibernate module implementation allows to replace code like this:
using (var session = _factory.OpenSession())
using (var tx = session.BeginTransaction())
{
  var solution = session.Load<SolutionEntity>(solutionId);
  solution.State = SolutionEntityState.Ready;
  session.Save(solution);
  tx.Commit();
}
with code like this:
var solution = session.Load<SolutionEntity>(solutionId);
solution.State = SolutionEntityState.Ready;

While doing that, Lokad.CQRS infrastructure ensures that:
  • Read and write operations are executed within a transaction, making sure that our reads and writes are safe for the concurrent processing.
  • Database changes are rolled back properly, if something goes wrong.

Last edited Apr 11, 2011 at 10:34 PM by AlexandrYZ, version 5

Comments

No comments yet.