top of page
perigticonramo

Using Multiple NHibernate Session Factories: A Practical Guide



As you said, you have already worked with single database and NHibernate, I do not think any specific code is needed. Its same, just multiple session factory instances. Anyway, I have copied my code at the end of answer.




Using Multiple NHibernate Session Factories



A previous CodeProject article described using NHibernate with ASP.NET; it offered guidelines for communicating with a single database. But, it is sometimes necessary to communicate with multiple databases concurrently. For NHibernate to do this, a session factory needs to exist for each database that you will be communicating with. But, as is often the case with multiple databases, some of the databases are rarely used. So, it may be a good idea to not create session factories until they're actually needed. This article picks up where the previous NHibernate with ASP.NET article left off, and describes the implementation details of this simple-sounding approach. Although the previous article focused on ASP.NET, the below suggestion is supported in both ASP.NET and Windows Forms.


Now that the database configuration has been defined in one or more config files, the NHibernate session manager needs to be informed about which session factories are available for use and where their respective config files reside. A solution that will provide a great amount of reuse is to create a custom config file reader. The web/app.config then states where each config file lives, as follows:


A remaining task is to modify the NHibernateSessionManager class from the original NHibernate with ASP.NET article so that it now manages multiple session factories. The general idea is that each session factory is stored in a hashtable using its associated config file path as the key. As described previously, this makes it easy to locate the session factory, or create a new one, if not found.


The legacy application I'm currently replacing features multiple databases for some insane reason. Luckily it's quite easy to get NHibernate to do joins across databases so long as they are on the same server. The technique is detailed by Hector Cruz in this thread on the NHibernate forum. The trick is to specify the schema you are addressing in each mapping file. Because the schema name simply becomes a table prefix, you can also use it to specify cross database joins. So long as you follow good practice and have one mapping file per entity, it means that, in theory, each entity could be persisted to a different database. I've put together a little project to show this working using Northwind. You can download the code here:


One developer explained me using this model. If there are unexpected changes to objects then these changes are tracked by NHibernate and when session is to be disposed then changes are flushed. Users probably see no errors but these appear in log files. Making database queries in transactions only mean that all unsaved changes during flush are unwanted side effects and developers must solve these issues.


NHibernate Profiler can aggregate related sessions under the same scope. By default, in web applications, we aggregate sessions which are opened in the same web page under the same scope. But we provide an API that you can use to aggregate related session in your applicatoin using a different strategy.


This is controlled using the adonet.batch_size setting in the configuration. If you set it to a number larger than zero, you can immediately start benefiting from reduced number of database calls. You can even set this value at runtime, using session.SetBatchSize().


Because we are using multiple sessions in this fashion, we can't really take advantage of NHibernate features that are meant to deal with this exact situation. The first step is to avoid using more than one session per request, and the next step is to follow the guidance on solving select N + 1 problems for NHibernate.


NHibernate Profiler has detected a large number of cache calls being made in a single session. Note that this alert is only applicable if you are using a distributed cache, if you are using a local cache, you can safely ignore this alert.


Even if we are only reading data, we should use a transaction, because using transactions ensures that we get consistent results from the database. NHibernate assumes that all access to the database is done under a transaction, and strongly discouragesany use of the session without a transaction.


NHibernate sessions are not thread safe, and attempting to use them in multiple threads requires careful synchronization. It is generally better to consider a session only useful within the thread that created it.


The second strategy is to use the classSpring.Data.TxScopeTransactionManager that uses .NET2.0 System.Transaction namespace and its corresponding TransactionScopeAPI. This is preferred when you are using multiple transactionalresources, such as multiple databases. Note that due to changes in themanner in which NHibernate manages its own transactions introduced inNHibernate 2.1.2 (and later), when using NHibernate 2.1.2 (and later) inthe context of the .NET System.Transaction class and itsTransactionScope API Spring.NET users are advised to use theSpring.Data.HibernateTxScopeTransactionManager classwhich is specifically designed to manage the new NHibernatetranscational model when used in the context of the System.TransactionAPI. The API of theSpring.Data.HibernateTxScopeTransactionManager classis functionally equivalent to that of theSpring.Data.HibernateTransactionManager class but itis designed to cooperate with the .NET System.TransactionTransactionScope API for NHibernate 2.1.2 (and later).


Many of the properties onLocalSessionFactoryObject are those you will commonlyconfigure, for example the property MappingAssembliesspecifies a list of assemblies to seach for hibernate mapping files. Theproperty HibernateProperies are the familiarNHibernate properties used to set typical options such as dialect anddriver class. The location of NHibernate mapping information can also bespecified using Spring's IResourceabstraction via the property MappingResources.The IResource abstraction supports opening an input stream fromassemblies, file system, and http(s) based on a Uri syntax. You can alsoleverage the extensibility of IResource and thereby allow NHibernate toobtain its configuration information from locations such as a databaseor LDAP.For other properties you can configure them as you normal usingthe file hibernate.cfg.xml and refer to it via theproperty ConfigFileNames. This property is a stringarray so multiple configuration files are supported.


Beginning with Spring.NET 1.3.1 there is direct support forcreating a new session factory per connection string (assuming thesame mapping files can be used across all databases connections). Tosupport this functionality,DelegatingLocalSessionFactoryObject subclassesLocalSessionFactoryObject and overrides the methodISessionFactory NewSessionFactory(Configurationconfig) so that it returns an implementation ofISessionFactory that selects among multipleinstances based on values in thread local storage, much like theimplementation of MultiDelegatingDbProvider. Notethat due to variations in the NHibernate project'sISessionFactory API, this approach is onlysupported under NHibernate 2.1.2 and NHibernate 3.0


For distributed transactions across multiple Hibernate sessionfactories, simply combine TxScopeTransactionManageras a transaction strategy with multipleLocalSessionFactoryObject definitions. Each of yourDAOs then gets one specific SessionFactory referencepassed into it's respective object property.


The default behavior of the module is that a single session iscurrently used for the life of the request. Refer to the earlier sectionon Transaction Management in this chapter for more information on howsessions are managed in the OpenSessionInViewModule. You can alsoconfigure in the application setting the EntityInterceptorObjectNameusing the keySpring.Data.NHibernate.Support.OpenSessionInViewModule.EntityInterceptorObjectNameand if SingleSession mode is used via the keySpring.Data.NHibernate.Support.OpenSessionInViewModule.SingleSession.If SingleSession is set to false, referred to as 'deferred close mode',then each transaction scope will use a new Session and kept open untilthe end of the web request. This has the drawback that the first levelcache is not reused across transactions and that objects are required tobe unique across all sessions. Problems can arise if the same object isassociated with more than one hibernate session.


Refer to the API documentation for information on overloadedconstructor. At the end of the using block the session is automaticallyclosed. All transactions within the scope use the same session, if youare using Spring's HibernateTemplate or using Spring's implementation ofNHibernate 1.2's ICurrentSessionContext interface. See other sections inthis chapter for further information on those usage scenarios.


When using Spring's Integration Testingsupport, you should make sure that the hibernate session isflushed so that the database is updated, as compared to just updatingthe hibernate session cache. You can implement a base class as shownbelow to help with the integration testing


NHibernate Second Level Cache exists at the Session Factory level, which means multiple user sessions can access a shared cache. Additionally, NHibernate 2nd level cache has a plug-able architecture so you can plug-in a third party distributed cache to it without any programming. NCache has implemented NHibernate Second Level Cache Provider and you can use it as your distributed cache for NHibernate without any code changes.


I have divided the API to transaction and session. There are some cases where I want to use session with out transaction, and there are times when I need multiple transaction in a single HTTP request.


it's raising another question - how to handle multiple database scenario? (that's why we provide manualy connection to session). Since there is no easy way (or at least i dont know any) to handle multiple databases in one solution with one config file. 2ff7e9595c


1 view0 comments

Recent Posts

See All

Google play store baixar apk uptodown

Google Play Store Baixar APK Uptodown: Como obter os melhores aplicativos para Android Se você é um usuário do Android, provavelmente...

Comments


bottom of page