Multiple databases

107 views
Skip to first unread message

jsmith

unread,
Apr 25, 2012, 8:58:33 AM4/25/12
to Fluent NHibernate
I am working on an application which has to access multiple databases.
I have been researching the best way to put entities and mapping
files:

1) Should the entities and mapping files for each database reside in a
different assembly?

2) Is it possible to put entities and mappings in the same assembly in
different folders (namespaces) and tell the configuration to
AddFromNamespace?

What is the most efficient way to create session factory? We are not
using AutoMappings

Dylan Beattie

unread,
Apr 25, 2012, 4:23:26 PM4/25/12
to fluent-n...@googlegroups.com
Assuming you're using SQL Server and can access all the databases using the same connection string by qualifying the table names, you can use a simple IClassConvention to map the entity namespaces into qualified database table names. The entire convention class looks like this:
public class SchemaPrefixConvention : IClassConvention {

		private string ExtractDatabaseName(string entityNamespace) {
			return (entityNamespace.Substring(entityNamespace.LastIndexOf('.') + 1));
		}

		public void Apply(IClassInstance instance) {
			instance.Schema(ExtractDatabaseName(instance.EntityType.Namespace) + ".dbo");
		}
	}
You then create your entity/model classes like:

namespace MyProject.Model.Entities.CustomerDB {
    public class Customer { }
    public class Invoice { }
}

namespace MyProject.Model.Entities.Shipping {
  public class Shipment { }
  public class DeliveryAddress { }
}

In our project, we use automapping so the convention is registered like so:

mappings.AutoMappings.Add(
  AutoMap
    .AssemblyOf<Customer>()
    .Where(t => t.Namespace == "MyProject.Model.Entities.CustomerDB")
    .Conventions.Add<SchemaPrefixConvention>()
    .UseOverridesFromAssemblyOf<Customer>()
);
mappings.AutoMappings.Add(
  AutoMap
    .AssemblyOf<Shipment >()
    .Where(t => t.Namespace == "MyProject.Model.Entities.Shipping")
    .Conventions.Add<SchemaPrefixConvention>()
    .UseOverridesFromAssemblyOf<Shipment>()
);

That said, I do not recommend you do this. We've ended up with a series of cross-database dependencies that seemed like a *really* good idea and have become a maintenance headache. I would strongly encourage you to build specific models/entities for each database (or rather, for each distinct business capability) and handle the dependencies and relationships explicitly by allowing your models to operate on interfaces exposed by other projects.

Hope this helps.

-D-



--
You received this message because you are subscribed to the Google Groups "Fluent NHibernate" group.
To post to this group, send email to fluent-n...@googlegroups.com.
To unsubscribe from this group, send email to fluent-nhibern...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/fluent-nhibernate?hl=en.


BobTodd

unread,
May 1, 2012, 9:46:57 AM5/1/12
to Fluent NHibernate
Having a schema convention is probably the easiest and quickest way to
perform queries across dbs on the same server.

When this assumption cannot be made, I've ended up with a
SessionFactory for each db

Sh#rp Architecture has some helper classes for supporting multiple
SessionFactories (by key) - you can simply decorate your repositories
with the following attribute, specifying which session factory key
should be used.

[SessionFactory("FactoryKeyNameGoesHere")]
public class CourseRepository :
NHibernateRepository<Course>, ICourseRepository, IDisposable
{ }

Dion

unread,
May 3, 2012, 3:38:41 AM5/3/12
to fluent-n...@googlegroups.com
In the project I'm currently working on, we're using MySql and therefore have the need to implement the Master-Slave pattern. IOW, single writable database and multiple read databases. My approach was to develop a custom session factory that is aware of read and writable databases. In some ways it contains similar functions to sharding in that it has the ability to implement different strategies i.e. round-robin db selection. The connections are stored as ISessionFactories on the custom class.

The custom session factory has methods that give the developer the option to open a read-only session or a read-write session. The developer will then need to decide which type of connection the functionality they're programming requires. We also use IoC extensively so the session factory is injected into the classes as dependencies. So when you request an read-only session, the session that is returned is a standard NHibernate ISession. Similarly I've exposed the ISessionFactory for operations like Evict().


Reply all
Reply to author
Forward
0 new messages