Coxy
Coxy

Reputation: 8928

NHibernate programmatic mapping file loading with embedded resources

My application supports both Oracle and MS SQL databases, with slightly different schemas having been implemented for each. One issue I've run into is a class that has an auto-increment primary key under MS SQL, but a manually-inserted primary key under Oracle.

Right now, the two different mappings for the class look like this:

Oracle:

<class lazy="false" name="EntityPropertyName" table="entity_property_name" >
<id name="ID" column="id" type="Int32" unsaved-value="-1">
  <generator class="increment" />
</id>
<property name="Name" column="name"/>

MS SQL:

<class lazy="false" name="EntityPropertyName" table="entity_property_name" >
<id name="ID" column="id" type="Int32" unsaved-value="-1">
  <generator class="native">
  </generator>
</id>
<property name="Name" column="name"/>

This isn't the worst thing in the world, because I can put them into different mapping files and load the correct one at runtime.

NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration();

            if (newDBType == CompanyName.AppName.Data.Enum.DatabaseType.MsSqlServer)
            {
                cfg.Properties["dialect"] = "NHibernate.Dialect.MsSql2000Dialect";
                cfg.Properties["connection.driver_class"] = "NHibernate.Driver.SqlClientDriver";
                cfg.AddFile("DataTypes\\MSSQLTypes.hbm.xml");
            }
            else
            {
                cfg.Properties["dialect"] = "NHibernate.Dialect.Oracle9Dialect";
                cfg.Properties["connection.driver_class"] = "NHibernate.Driver.OracleClientDriver";
                cfg.AddFile("DataTypes\\OracleTypes.hbm.xml");
            }

            cfg.Properties["connection.provider"] = "NHibernate.Connection.DriverConnectionProvider";

            cfg.Properties["connection.connection_string"] = connectionString;

            cfg.AddAssembly("CompanyName.AppName.Data");

            Sessions = cfg.BuildSessionFactory();

The thing I dislike about this strategy though is that I now have some ugly XML files in my program's bin directory, which need to be there or the application won't work. It would be a lot better if I could embed the different files into the resource like I can with my main mapping file, but choose whether to load each file or not at runtime.

Is there any way to do this, or perhaps a different way to solve the problem?


Edit: Thank you, Cristian! You did understand the question, I was just unaware that resources could be loaded by NHibernate like that. Thinking on it, I suppose it makes sense for the AddAssembly method would have to have some way to enumerate and load the resources that it finds!

My solution ended up being:

NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration();

            if (newDBType == CompanyName.AppName.Data.Enum.DatabaseType.MsSqlServer)
            {
                cfg.Properties["dialect"] = "NHibernate.Dialect.MsSql2000Dialect";
                cfg.Properties["connection.driver_class"] = "NHibernate.Driver.SqlClientDriver";
                cfg.AddInputStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("CompanyName.AppName.Data.DataTypes.MSSQLTypes.hbm.xml"));
            }
            else
            {
                cfg.Properties["dialect"] = "NHibernate.Dialect.Oracle9Dialect";
                cfg.Properties["connection.driver_class"] = "NHibernate.Driver.OracleClientDriver";
                cfg.AddInputStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("CompanyName.AppName.Data.DataTypes.OracleTypes.hbm.xml"));
            }

            cfg.Properties["connection.provider"] = "NHibernate.Connection.DriverConnectionProvider";

            cfg.Properties["connection.connection_string"] = connectionString;

            cfg.AddInputStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("CompanyName.AppName.Data.DataTypes.Types.hbm.xml"));

            Sessions = cfg.BuildSessionFactory();

Upvotes: 0

Views: 7708

Answers (1)

Cristian Libardo
Cristian Libardo

Reputation: 9258

I might be missing your crucial point. NHibernate is quite flexible in how you can feed it the mapping files. e.g.

cfg.AddInputStream(assembly.GetManifestResourceStream("MyNamespace.MyEmbeddedresource.hbm.xml"));

or a custom built xml string:

cfg.AddXml(myCustomBuildXmlString);

You can also add mappings programmatically directly but that's a bit trickier.

Upvotes: 2

Related Questions