Fluent NHibernate + multiple databases
Asked Answered
R

4

9

My project needs to handle three databases, that means three session factories. The thing is if i do something like this with fluent nhibernate:

.Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly()))

the factories would pick up all the mappings, even the ones that correspond to another database

I've seen that when using automapping you can do something like this, and filter by namespace:

.Mappings(m => m.AutoMappings.Add(
    AutoMap
       .AssemblyOf<Product>()
       .Where(t => t.Namespace == "Storefront.Entities")))

I havent found anything like this for fluent mappings, is it possible?? The only solutions I can think of are: either create separate assemblies for each db mapping classes or explicitly adding each of the entities to the factory configuration.

I would prefer to avoid both, if possible. Thanks.

Robi answered 16/4, 2010 at 20:19 Comment(2)
I'd advise one mapping assembly per database in this instance. It's a good separation of concerns and should be easy for any other developer to understand.Persuade
Seems like I need to put all the entitiy classes in another project and the other project for the second db.Virtual
R
6

I've implemented exactly this using (my own) Attribute on the Fluent mapping file to dictate which DB the entity belongs in. I've also got a concept of a 'default' database, and mapping files without an attribute are assumed to reside in the default DB (it may cut down on the number of classes you need to decorate). I then have initialisation code which creates a Session Factory per database, and for each, uses reflection to find all ClassMap classes,examines the attribute to determine which DB it belongs to, and registers each ClassMap accordingly.

A mapping file example:

  [FluentNHibernateDatabase("MySecurityDatabase")]
  public class SystemUserMap : ClassMap<SystemUser>
  {
    public SystemUserMap()
    {
      Id(x => x.SystemUserId);
      Map(x => x.LoginId);
      Map(x => x.LoginPassword);
      Map(x => x.UserFirstName);
      Map(x => x.UserSurname);
      References(x => x.UserOrganisation, "OrganisationId");
    }
  }

Obviously I've defined a list of the DBs that are referenced/used.
My implementation works so far as I've taken it, but I've hit a snag (that I hope someone can help out with):

I've asked my question here: How to identify a particular entity's Session Factory with Fluent NHibernate and Multiple Databases

Rosebud answered 23/4, 2010 at 11:55 Comment(5)
In this scenario, where are you making use of the attribute? I know it would be in the mapping configuration, but any chance you could provide more detail of your implementation? Thanks!Sewing
Where is the FluentNHibernateDatabase attribute and how you define the Fluently.Configure()?Virtual
The Attribute is my own and I use it to identify the DB that a particular class must be registered to (the parameter to the attribute is the name I've given to my DB). I've implemented such that I have what I consider the 'default' DB, and all Map files that relate to entities in that DB do not need the attribute (or, inversely: All map files without the attribute are assumed to be aimed at the default DB).Rosebud
As for applying the 'which DB' rules ... that's a little complex. In summary: I've written a registration operation which runs on app startup. I have a method "void AddFluentMappings(FluentNHibernate.Cfg.MappingConfiguration mappingConfig)" which adds the mappings relevant to a particular DB. This method uses reflection to determine all the classmap<> descendants classes in the app and loops through each of them checking for the attribute and, if found, checking if that attributes 'DBName' matches the one currently being registered.Rosebud
To use this AddFluentMappings() method I make a call "fluentConfiguration.Mappings(AddFluentMappings);" where fluentConfiguration is of type FluentConfiguration.Rosebud
G
5

The easy way of doing this is to put the database name into the Schema

public sealed class CustomerMapping: ClassMap<Customer>
{
    public CustomerMapping()
    {
        Schema("Northwind.dbo");
        Table("Customer");
    }
}

public sealed class Customer2Mapping: ClassMap<Customer2>
{
    public CustomerMapping()
    {
        Schema("Northwind2.dbo");
        Table("Customer");
    }
}

Then, provided all tables are accessible on the same connection string, you only need one session factory

Glossy answered 28/3, 2012 at 15:18 Comment(0)
C
1

You can also filter by types. Here's a line of commented code from a "green field" AutoPersistenceModel I use in the same assembly as a "brown field one" (ie, two databases). But there is only one type I need to filter on, so I haven't bothered to split out a legacy assembly. If you have got lots of them per db then splitting them by assemblies is probably going to be best IMO.

It would be cool if FNH could provide some sort of built in multi-db support but I don't know how that really could be done; some sort of dictionary of SessionFactories maybe but every situation is just so unique.

HTH,
Berryl

    /// <summary>
    /// This would simply call <see cref="AutoMapHelpers.GetAutoMappingFilter"/> but we need to 
    /// exclude <see cref="LegacyProject"/> also for now.
    /// </summary>
    private static bool _getIncludedTypesFilter(Type t) {
        return _isNotLegacy(t) && AutoMapHelpers.GetAutoMappingFilter(t);
    }
    private static bool _isNotLegacy(Type t) { return !t.Equals(typeof(LegacyProject)); }
Cerography answered 16/4, 2010 at 22:17 Comment(0)
C
0

Although it is very late response, I suggest you to go through the following url which infact has some solution to be solved and hence you can find the solution in answers however. Here is the solution to your answer which was implemented with the help of url

By the solution implemented by me you can only implement database first model as of now. Try Avoiding GenerateSchema Method in the Question posted by me at mentioned url, because it is still not implemented as if you use that method, you will able to see the multiple databases with same tables and relationships created.

Coates answered 30/6, 2012 at 18:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.