3
votes

Currently I have two databases of identical structure (one is for temp changes, another is live one). I use same NHibernate entities, mappings and repositories to access both databases. Only connection string is changed when creating Session.

Now I need to change approach and merge those two DBs into one. I'm planning to separate equally named tables by introducing different schemas for them. Sounds easy. But the problem arised when I checked how to update my NHibernate mappings so that they support either one schema or another - it seems that map classes support only parameterless constructors (at least all methods to add mappings to NHibernate configuration doesn't suppose any constructor parameters).

Here is some sample code to demonstrate what I'd like to achieve:

public class MyEntityMap : ClassMap<MyEntity>
{
    public MyEntityMap ()
    {
        Table("MyEntities");
        Schema("a");    //I can specify schema as a constant here, but I need it to be variable: constructor either parameter or changable in other way
        Id(x => x.Id, "Id");
        Map(x => x.Name, "Name").Length(100);
    }
}

When creating NHibernate configuration there are the following options to add mappings to it (three method calls are shown just for options, I use single call to AddFromAssemblyOf currently):

Fluently.Configure()
        .Database(MsSqlConfiguration.MsSql2008.ConnectionString("MyConnectionString"))
        .Mappings(m => m.FluentMappings.AddFromAssembly(typeof (MyEntityMap).Assembly))
        .Mappings(m => m.FluentMappings.AddFromAssemblyOf<MyEntityMap>())
        .Mappings(m => m.FluentMappings.Add<MyEntityMap>)

Obviously neither option supports parameterized constructor of ClassMap derived classes and I can't see how else can I specify schema for all mappings at once.

Solutions I see (but which seem to be an overkill):

  1. Manually create 2 derived classes from each mapping class and place them in different assemblies. So that each class provide it's value for schema constant.
  2. Autogenerate 2 mapping classes, derived from each 'base' mapping using System.Emit. Use assemblies, generated at runtime to pass to AddMappingFromAssembly method.

Am I missing something? Is there an easy way to specify which schema to use for all repositories, created using specified NHibernate configuration?

1
Maybe the answer is use conventions, i have never used them with NHibernate mapping by code. Take at look here fabiomaulo.blogspot.mx/2011/07/… - Najera
MsSql2008Configuration : looks as a custom class specific to your code. I guess it does inherit from NHibernate.Cfg.Configuration, doesn't it? - Frédéric
@Frédéric, you are right. Replaced code, dependent on our custom data-layer with corresponding pure FluentNHibernate configuration code. - Sasha
Since what answers your actual need does not match your question, maybe should you edit and add some notice in it (or even reword your question, especially its title). It would helps this question & answer to be found and useful for others. - Frédéric
@Frédéric, while the answer was surprisingly different from what I expected, the question I believe reflected what I wanted to get and so is searchable. I rephrased it slightly to become more general - Sasha

1 Answers

2
votes

Rather than adapting all the mappings, why not use default_schema configuration parameter?

Or have I missed something causing such a global switch to be inadequate for your case?

Of course this will require to cease specifying in your mapping which schema to use on each table having to switch schema.

To configure this setting by code, you may add it through:

var configuration = new NHibernate.Cfg.Configuration();
...
configuration.AddProperties(
    new Dictionary<string, string>
    {
        { NHibernate.Cfg.Environment.DefaultSchema, "yourDbName.yourSchema" }
    });
...
var sessionFactory = configuration.BuildSessionFactory();

Or set them with:

configuration.Properties[NHibernate.Cfg.Environment.DefaultSchema] =
    "yourDbName.yourSchema";

Specifying db name is optional and not supported by all databases, but may improve performances with SQL-Server.