Skip to content

Instantly share code, notes, and snippets.

@ianfnelson
Created October 18, 2010 15:15
Show Gist options
  • Save ianfnelson/632368 to your computer and use it in GitHub Desktop.
Save ianfnelson/632368 to your computer and use it in GitHub Desktop.
Unit of Work
namespace Marshalls.Leads.DataAccess
{
using System;
using System.Collections.Generic;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using Marshalls.Leads.Facilities;
using Marshalls.Leads.Facilities.Configuration;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Context;
using NHibernate.Mapping;
using NHibernate.Tool.hbm2ddl;
/// <summary>
/// NHibernate Unit of Work class.
/// </summary>
public class UnitOfWork : IUnitOfWork
{
private static ISessionFactory sessionFactory;
private static Configuration configuration;
/// <summary>
/// Gets the session. You must Start the Unit of Work before calling this.
/// </summary>
public static ISession Session
{
get { return sessionFactory.GetCurrentSession(); }
}
public static void BeginTransaction()
{
if (Session.Transaction != null && Session.Transaction.IsActive)
{
return;
}
Session.BeginTransaction();
}
public static void Commit()
{
if (Session.Transaction != null && Session.Transaction.IsActive)
{
try
{
Session.Transaction.Commit();
}
catch (Exception)
{
Session.Transaction.Rollback();
throw;
}
}
else
{
Session.Flush();
}
}
/// <summary>
/// Configures NHibernate.
/// </summary>
/// <param name="environment">Environment in which to run.</param>
/// <param name="connectionString">Connection string - if none specifed, uses SQLLite.</param>
public void Configure(DataEnvironment environment, string connectionString)
{
// NHProf is a powerful real-time visual debugger allowing a development
// team to gain valuable insight and perspective into their use of ORMs.
// I can't rate it highly enough.
// Like SQL Profiler, you really don't want it running in production though.
// http://nhprof.com/
if (Config.Settings.NHProfEnabled || environment == DataEnvironment.Test)
{
HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize();
}
// we will poke some additional properties into the config
var additionalProperties = new Dictionary<string, string>();
// Change the session context depending on the environment.
if (environment == DataEnvironment.Web)
{
additionalProperties.Add("current_session_context_class", typeof(WebSessionContext).FullName);
}
else
{
additionalProperties.Add("current_session_context_class", typeof(CallSessionContext).FullName);
}
// Yum, stats!
additionalProperties.Add("generate_statistics", "true");
if (environment == DataEnvironment.Test && string.IsNullOrEmpty(connectionString))
{
this.ConfigureSqlite(additionalProperties);
}
else
{
this.ConfigureMsSql(additionalProperties, connectionString);
}
}
/// <summary>
/// Exports the schema to the database.
/// Don't call this from production code, for goodness sake!
/// </summary>
public void SchemaExport()
{
new SchemaExport(configuration).Execute(false, true, false, Session.Connection, null);
}
/// <summary>
/// Begin a new unit of work.
/// </summary>
/// <returns>NHibernate Session</returns>
public object Start()
{
// Stash a new session where we can get at it at any time. NHibernate already
// has a CurrentSessionContext class for keeping sessions somewhere accessible.
CurrentSessionContext.Bind(sessionFactory.OpenSession());
return Session;
}
/// <summary>
/// End the current unit of work.
/// </summary>
public void End()
{
// close the session
Session.Close();
// Session is disposable, and therefore it's good to call Dispose() once we're done with it.
Session.Dispose();
// unbind the session from the context as we won't be needing it.
CurrentSessionContext.Unbind(sessionFactory);
}
private void ConfigureSqlite(IDictionary<string, string> additionalProperties)
{
configuration = new Configuration();
// If we are testing and no connection string supplied, use an in memory SQL Lite Database.
// It's fast as shit off the proverbial shovel and no install is required.
Fluently.Configure(configuration)
.Database(
SQLiteConfiguration
.Standard
.InMemory()
.ShowSql())
.Mappings(m => m
.FluentMappings.AddFromAssemblyOf<UnitOfWork>()
.Conventions.AddFromAssemblyOf<UnitOfWork>())
.ExposeConfiguration(x =>
x.SetProperty("connection.release_mode", "on_close"))
.ExposeConfiguration(x =>
x.AddProperties(additionalProperties))
.BuildSessionFactory();
// SQLLite doesn't understand the concept of db schemas, it thinks the schema is
// a database name.
// So, we change the mappings so that, for example "dbo.cv_Alert" becomes "dbo_cv_Alert".
foreach (PersistentClass pc in configuration.ClassMappings)
{
if (pc.Table.Name.Contains("."))
{
pc.Table.Name = pc.Table.Name.Replace(".", "_");
}
}
sessionFactory = configuration.BuildSessionFactory();
}
private void ConfigureMsSql(IDictionary<string, string> additionalProperties, string connectionString)
{
configuration = new Configuration();
sessionFactory = Fluently.Configure(configuration)
.Database(
MsSqlConfiguration
.MsSql2005
.ConnectionString(c => c.Is(connectionString))
.Cache(c => c
.UseQueryCache()
.ProviderClass("NHibernate.Caches.SysCache2.SysCacheProvider, NHibernate.Caches.SysCache2"))
.ShowSql()
.AdoNetBatchSize(100))
.Mappings(m => m
.FluentMappings.AddFromAssemblyOf<UnitOfWork>()
.Conventions.AddFromAssemblyOf<UnitOfWork>())
.Mappings(m =>
m.HbmMappings.AddFromAssemblyOf<UnitOfWork>())
.ExposeConfiguration(x =>
x.AddProperties(additionalProperties))
.BuildSessionFactory();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment