Click here to Skip to main content
Click here to Skip to main content

Using Multiple NHibernate Assemblies with NHSessionManager

, 1 Feb 2007
Rate this:
Please Sign up or sign in to vote.
This article describes how NHSessionManager can be configured to use multiple NHibernate assemblies

Introduction

In a previous article NHibernate Best Practices with ASP.NET, Generics and Unit Tests by Bill McCafferty, NHSessionManager is configured via App/Web config simply to work with NHibernate core assembly. Since NHSessionManager and other assemblies (Core, Data and Test) are located in the same solution, this simple way is enough for all practical purposes. But for the sake of code reuse, we can think of reorganising the NHibernate utility classes (NHSessionManager, DomainObject, NHGenericDao) and interfaces (IGenericDao) in a separate solution/project. When this is the case, we need a more generic way to specify NHSessionManager configuration.

Another article Using NHibernate with Multiple Databases again by Bill McCafferty is a very good example of how to extend the configuration system of .NET.

Extending Configuration System

We need a configuration section handler and configuration element specification in order to specify multiple NHibernate assemblies via App/Web config.

Our goal is to handle a configuration section like this one:

  <configSections>
    <section name="nhibernate" 
	type="System.Configuration.NameValueSectionHandler, 
	System, Version=1.0.1.0,Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,
	log4net, Version=1.2.9.0, Culture=neutral, PublicKeyToken=b32731d11ce58905"/>
    <section name="castle" 
	type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, 
	Castle.Windsor"/>
    <section name="nHibernateAssemblies" 
	type=" NHibernateSample.Common.Configuration.NHAssembliesSection, 
	NHibernateSample.Common"/>
  </configSections>
  
  <nHibernateAssemblies>
    <NhAssemblies>
      <clearAssemblies />
      <NhAssembly name="Core assembly 1" assembly="ProjectName1.Core"/>
      <NhAssembly name="Another core assembly" assembly="ProjectName2.Core"/>
    </NhAssemblies>
  </nHibernateAssemblies>

NHAssemblyElement

NHAssemblyElement is inherited from ConfigurationElement placed in System.Configuration namespace.

The NHAssemblyElement class has two properties:

  • Name for holding descriptive name for the core assembly
  • Assembly for holding name of the assembly we want NHSessionManager to load
public class NHAssemblyElement : ConfigurationElement
{
  public NHAssemblyElement( )
  {

  }

  public NHAssemblyElement( string name, string assembly )
  {
    Name = name;
    Assembly = assembly;
  }

  [ConfigurationProperty("name", IsRequired = true, IsKey = true, 
	DefaultValue = "Not Supplied")]
  public string Name
  {
    get { return (string)this["name"]; }
    set { this["name"] = value; }
  }

  [ConfigurationProperty("assembly", IsRequired = true, DefaultValue = "Not Supplied")]
  public string Assembly
  {
    get { return (string)this["assembly"]; }
    set { this["assembly"] = value; }
  }
}

NHAssembliesCollection

NHAssembliesCollection is inherited from the standard ConfigurationElementCollection class.

[ConfigurationCollection(typeof(NHAssemblyElement))]
public class NHAssembliesCollection : ConfigurationElementCollection
{
  public NHAssembliesCollection( )
  {
    NHAssemblyElement element = (NHAssemblyElement)CreateNewElement();
    Add(element);
  }

  public override ConfigurationElementCollectionType CollectionType
  {
    get
    {
      return ConfigurationElementCollectionType.AddRemoveClearMap;
    }
  }

  protected override ConfigurationElement CreateNewElement( )
  {
    return new NHAssemblyElement();
  }

  protected override object GetElementKey( ConfigurationElement element )
  {
    return ((NHAssemblyElement)element).Name;
  }

  public NHAssemblyElement this[int index]
  {
    get
    {
      return (NHAssemblyElement)BaseGet(index);
    }
    set
    {
      if (BaseGet(index) != null)
      {
        BaseRemoveAt(index);
      }

      BaseAdd(index, value);
    }
  }

  new public NHAssemblyElement this[string name]
  {
    get
    {
      return (NHAssemblyElement)BaseGet(name);
    }
  }

  public int IndexOf( NHAssemblyElement assembly )
  {
    return BaseIndexOf(assembly);
  }

  public void Add( NHAssemblyElement assembly )
  {
    BaseAdd(assembly);
  }

  protected override void BaseAdd( ConfigurationElement element )
  {
    BaseAdd(element, false);
  }

  public void Remove( NHAssemblyElement assembly )
  {
    if (BaseIndexOf(assembly) >= 0)
    {
      BaseRemove(assembly.Name);
    }
  }

  public void RemoveAt( int index )
  {
    BaseRemoveAt(index);
  }

  public void Remove( string name )
  {
    BaseRemove(name);
  }

  public void Clear( )
  {
    BaseClear();
  }
}

NHAssembliesSection

NHAssembliesSection inherits from the standard ConfigurationSection and implements the section handler specified in the configuration file as:

<section name="nHibernateAssemblies" 
	type=" NHibernateSample.Common.Configuration.NHAssembliesSection, 
	NHibernateSample.Common"/>

The code is as follows: 

public class NHAssembliesSection : ConfigurationSection
{
  [ConfigurationProperty("NhAssemblies", IsDefaultCollection = false)]
  [ConfigurationCollection(typeof(NHAssembliesCollection), 
	AddItemName = "NhAssembly", ClearItemsName = "clearAssemblies")]
  public NHAssembliesCollection NHAssemblies
  {
   get
   {
    NHAssembliesCollection assembliesCollection = 
	(NHAssembliesCollection)base["NhAssemblies"];
    return assembliesCollection;
   }
  }
}

Little Modification to NHSessionManager

In NHSessionManager, we have to change the InitSessionFactory() method a little bit.

The original version provided by Bill McCafferty implements loading of NHibernate assemblies with the following code:

private void InitSessionFactory() 
{
 NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration();
 // The following makes sure the web.config contains 
 // a declaration for the HBM_ASSEMBLY appSetting
 if (ConfigurationManager.AppSettings["HBM_ASSEMBLY"] == null || 
     ConfigurationManager.AppSettings["HBM_ASSEMBLY"] == "") 
 {
  throw new ConfigurationErrorsException
	("NHibernateManager.InitSessionFactory: \"HBM_ASSEMBLY\" must be " +
    "provided as an appSetting within your config file. \"HBM_ASSEMBLY\" 
	informs NHibernate which assembly " +
    "contains the HBM files. It is assumed that the HBM files are embedded resources. 
	An example config " +
    "declaration is <add value="\" key="\" />");
 }
 
 cfg.AddAssembly(System.Configuration.ConfigurationManager.AppSettings["HBM_ASSEMBLY"]);
 sessionFactory = cfg.BuildSessionFactory();
}

The code above handles a configuration file as the following one:

<appSettings>
 <add key="HBM_ASSEMBLY" value="NHibernateSample.Core"/>
</appSettings>

As I mentioned in the introduction of the article, with this NHSessionManager implementation we have to change NHSessionManager source code and recompile every time we want to handle another NHibernate assembly.

Our alternative InitSessionFactory implementation of NHSessionManager code looks like the following:

private void InitSessionFactory( )
{
  NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration();

  NHAssembliesSection nhAssembliesSection = 
	ConfigurationManager.GetSection("nHibernateAssemblies") as NHAssembliesSection;
  
  if(nhAssembliesSection == null)
  {
    throw new ConfigurationErrorsException
	("nHibernateAssemblies section not defined in application configuration!");
  }

  foreach(NHAssemblyElement element in nhAssembliesSection.NHAssemblies)
  {
    try
    {
      cfg.AddAssembly(element.Assembly);
    }
    catch (Exception e)
    {
      throw new Exception(" Can not add assembly! " + e.Message, e.InnerException);
    }
  }

  try
  {
    sessionFactory = cfg.BuildSessionFactory();
  }
  catch (Exception e)
  {
    throw new Exception(" Can not create session factory! " + 
	e.Message, e.InnerException);
  }
}

History

  • 1st February, 2007: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Ali Ozgur
Team Leader PragmaTouch
Turkey Turkey
- Software developer
- Has BS degree in Computer Engineering
- Has MBA degree
- Programmed with C, C++, Delphi, T-SQL and recently C#
- Little educational experience with Prolog
- Feel enthusiasm about NHibernate and LINQ
- Love to develop on Cuyahoga Web Framework
- Developer of PragmaSQL Editor
(Code Project Members Choice Winner for 2009 and 2010)
- Developed JiraTouch and MoodleTouch for iPhone
- PragmaTouch Lead (www.pragmatouch.com)
Follow on   Twitter

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web01 | 2.8.140827.1 | Last Updated 2 Feb 2007
Article Copyright 2007 by Ali Ozgur
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid