-
Notifications
You must be signed in to change notification settings - Fork 23
NHibernate Facility Quick Start
rarous edited this page Apr 30, 2013
·
3 revisions
In your App_Start or similar entry point to your application, create a new WindsorContainer:
using Castle.Facilities.NHibernate,
// ...
private WindsorContainer GetWindsorContainer()
{
var c = new WindsorContainer();
c.AddFacility<AutoTxFacility>();
c.Register(Component.For<INHibernateInstaller>().ImplementedBy<ExampleInstaller>());
c.AddFacility<NHibernateFacility>();
return c;
}
The NHibernate Facility will install all of its requirements.
Your NHibernate Installer implements this interface:
using System.Diagnostics.Contracts;
using Castle.Services.Transaction;
using FluentNHibernate.Cfg;
using NHibernate;
/// <summary>
/// Register a bunch of these; one for each database.
/// </summary>
[ContractClass(typeof(INHibernateInstallerContract))]
public interface INHibernateInstaller
{
/// <summary>
/// Is this the default session factory
/// </summary>
bool IsDefault { get; }
/// <summary>
/// </summary>
string SessionFactoryKey { get; }
/// <summary>
/// An interceptor to assign to the ISession being resolved through this session factory.
/// </summary>
Maybe<IInterceptor> Interceptor { get; }
/// <summary>
/// Build a fluent configuration.
/// </summary>
/// <returns>A non null fluent configuration instance that can
/// be used to further configure NHibernate</returns>
FluentConfiguration BuildFluent();
/// <summary>
/// Call-back to the installer, when the factory is registered
/// and correctly set up in Windsor..
/// </summary>
/// <param name="factory"></param>
void Registered(ISessionFactory factory);
}
an example implementation looks like this:
internal class ExampleInstaller : INHibernateInstaller
{
private readonly Maybe<IInterceptor> _Interceptor;
public ExampleInstaller()
{
_Interceptor = Maybe.None<IInterceptor>();
}
public ExampleInstaller(IInterceptor interceptor)
{
_Interceptor = Maybe.Some(interceptor);
}
public Maybe<IInterceptor> Interceptor
{
get { return _Interceptor; }
}
public bool IsDefault
{
get { return true; }
}
public string SessionFactoryKey
{
get { return "sf.default"; }
}
public FluentConfiguration BuildFluent()
{
return Fluently.Configure()
.Database(MsSqlConfiguration.
MsSql2008.
DefaultSchema("dbo").
ConnectionString(c => c.FromConnectionStringWithKey("test")))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<ThingMap>());
}
public void Registered(ISessionFactory factory)
{
}
}
Thing looks like this:
using System;
// ...
public class Thing
{
[Obsolete("NHibernate's c'tor")]
protected Thing()
{
}
public Thing(double val)
{
Value = val;
}
public Guid ID { get; protected set; }
public double Value { get; set; }
}
and ThingMap like this:
using FluentNHibernate.Mapping;
// ...
public class ThingMap : ClassMap<Thing>
{
public ThingMap()
{
Not.LazyLoad();
Id(x => x.ID).GeneratedBy.GuidComb();
Map(x => x.Value).Column("val");
}
}
A possible usage would now be a service that saves a new Thing:
[Test]
public void SavingWith_Transient_Lifestyle()
{
// in your app_start:
c.Register(Component.For<ServiceUsingTransientSessionLifestyle>().LifeStyle.HybridPerTransactionTransient());
// your controller calls:
using (var scope = new ResolveScope<ServiceUsingTransientSessionLifestyle>(c))
{
scope.Service.SaveNewThing();
Assert.That(scope.Service.VerifyThing(), Is.Not.Null);
}
}
// ... and the service would have this code:
// fields
private readonly Func<ISession> _Session;
// constructor:
public TearDownService(Func<ISession> session)
{
Contract.Requires(session != null);
_Session = session;
}
// and service-method
[Transaction]
public virtual void SaveNewThing()
{
_Logger.DebugFormat("save new thing");
using (var session = _GetSession())
{
// at KTH this is an arbitrary number
_Id = (Guid) session.Save(new Thing(17.0));
_Logger.DebugFormat("exiting using-block of session");
}
}
Want logging? In your entry point:
using log4net;
// ...
XmlConfigurator.Configure();
and in your App.config file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<connectionStrings>
<add name="test" connectionString="Data Source=.;Initial Catalog=TxTests;Integrated Security=SSPI"/>
</connectionStrings>
<log4net debug="false">
<appender name="DebugAppender" type="log4net.Appender.DebugAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline"/>
</layout>
</appender>
<appender name="TraceAppender" type="log4net.Appender.TraceAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level - %message%newline"/>
</layout>
</appender>
<root>
<level value="DEBUG"/>
<appender-ref ref="TraceAppender"/>
<!--<appender-ref ref="DebugAppender"/>-->
</root>
<logger name="NHibernate">
<level value="INFO"/>
</logger>
<logger name="NHibernate.Impl">
<level value="DEBUG"/>
</logger>
<logger name="NHibernate.Engine.Loading">
<level value="ERROR" />
</logger>
<logger name="Castle.Services.Transaction">
<level value="DEBUG"/>
</logger>
</log4net>
<!--<system.diagnostics>
<sources>
--><!--Verbose--><!--
<source name="System.Transactions" switchValue="Information">
<listeners>
<add name="tx"
type="Castle.Services.Transaction.Tests.TxTraceListener, Castle.Services.Transaction.Tests"/>
</listeners>
</source>
</sources>
</system.diagnostics>-->
</configuration>
Have fun!