Split NHibernate Domain Objects Needs Loading Multipule HBM Assemblies

With tens of NHibernate classes and hbm files generated, I realized it’s time to split them to different project/assembly. After finished split, I got the familiar unmapped class error, same one when I forgot set hbm file to embeded resource. By copying those hbm files back to the original project, this problem went away. But, shouldn’t assembly and class files always sit in the same project?

Definitely yes, something must be wrong here. I looked into the framework/demo (from Billy McCafferty). The problem is in NHibernateSessionManager, the Configureation.AddAssembly only takes one filename. So I made a small change:

App.config
<appSettings>
<add key=”HBM_ASSEMBLY” value=”Assembly1, Assembly2″/>
</appSettings>

NHibernateSessionManager.InitSessionFactory()

Configuration cfg = new Configuration();
string assembly = ConfigurationManager.AppSettings[“HBM_ASSEMBLY”];

if (assembly.Contains(“,”) )
{
foreach (string a in assembly.Split(‘,’))
cfg.AddAssembly(a);

}else{
cfg.AddAssembly(assembly);
}

sessionFactory = cfg.BuildSessionFactory();

Wala, back to all green now!

For configuration, I am using basic style, adding everything into <nhibernate> section then set the assembly in <appSettings>.

<appSettings>
<add key=”HBM_ASSEMBLY” value=”MyAssembly”/>
</appSettings>
<nhibernate>
<add key=”hibernate.connection.provider” value=”NHibernate.Connection.DriverConnectionProvider”/>
<add key=”hibernate.dialect” value=”NHibernate.Dialect.MsSql2000Dialect”/>
<add key=”hibernate.connection.driver_class” value=”NHibernate.Driver.SqlClientDriver”/>
<add key=”hibernate.connection.connection_string” value=”…” />
<add key=”hibernate.connection.isolation” value=”ReadCommitted”/>
<add key=”hibernate.show_sql” value=”true”/>
<add key=”hibernate.mapping.assembly” value=”MyAssembly”/>
</nhibernate>

I tried to add hibernate.mapping.assembly key into nhibernate section, didn’t work. But in Billy’s new sessionFactory configuration style, (which can support multiple db connections)

App.config:
<nhibernateSettings>
<sessionFactories>
<clearFactories />
<sessionFactory name=”northwind” factoryConfigPath=”C:\absolute_path\NorthwindNHibernate.config” isTransactional=”true” />
</sessionFactories>
</nhibernateSettings>

NorthwindNHibernate.config:
<hibernate-configuration xmlns=”urn:nhibernate-configuration-2.2″ >
<session-factory name=”northwind”>
<property name=”dialect”>NHibernate.Dialect.MsSql2005Dialect</property>
<property name=”connection.provider”>NHibernate.Connection.DriverConnectionProvider</property>
<property name=”connection.driver_class”>NHibernate.Driver.SqlClientDriver</property>
<property name=”connection.connection_string”>Data Source=.\SQLExpress;Database=Northwind;Integrated Security=SSPI;</property>
<property name=”connection.isolation”>ReadCommitted</property>
<property name=”default_schema”>Northwind.dbo</property>
<!– HBM Mapping Files –>
<mapping assembly=”EnterpriseSample1.Core” />
</session-factory>
</hibernate-configuration>

The mapping assembly can be taken automatically by:

ISessionFactory sessionFactory = (ISessionFactory) sessionFactories[sessionFactoryConfigPath];

Unfortunately, I tried to add multiply assemblies in this session factory configuration style, also failed.

I downloaded the source code of NHibernate, in protected Configuration DoConfigure(XmlDocument doc):

……
foreach (XmlNode mapElement in sfNode.ChildNodes)
{
string elemname = mapElement.LocalName;
if (“mapping”.Equals(elemname))
{
XmlAttribute rsrc = mapElement.Attributes[“resource”];
XmlAttribute file = mapElement.Attributes[“file”];
XmlAttribute assembly = mapElement.Attributes[“assembly”];
if (rsrc != null)
{
……
}
else if (assembly != null)
{
log.Debug(name + “<-” + assembly.Value);
AddAssembly(assembly.Value);
}

Which proofs NHibernate always assume each factory can only have one assembly, even you can load more than one by calling cfg.AddAssembly() directly. But I tried call cfg.AddAssembly() with cfg.Configure() together, didn’t work, all kids of errors based on different combinations. I gave up finally.

Meanwhile, I don’t like writing absolute path to the session factory in configuration. I can change it to relative one, but needs to set the compile action to “content” to avoid copying it to debug folder manually then.

Advertisements

2 thoughts on “Split NHibernate Domain Objects Needs Loading Multipule HBM Assemblies

  1. I had the same problem…three assembly and a relation many-to-one between two class mapping on different assembly..I fixed the problem with:

    many-to-one name=”Entity” class=”Namespaces.Foo, SampleAssembly” outer-join=”true”

    SampleAssembly is the father assembly.

Comments are closed.