As a guess, have you tried to reuse the Configuration object?
If only connection string or database name changes, you can cache the 
Configuration and re-use it. It’s one of the most expensive operations when 
bootstrapping NHibernate...

Valeriu

From: Kerry 
Sent: Wednesday, May 29, 2013 3:48 PM
To: [email protected] 
Subject: [nhusers] Bootstrapping with multiple Session Factories

We have a need in our app to support multiple "connections" to different 
databases, with each connection supporting the same set of mappings.  We have a 
huge number of mappings (this is a decade-old legacy application), and each 
connection and database has the same schema.  We recently added a feature to 
the application that allows a user on one connection to view data on all of the 
other connections, which requires having all of the connections available at 
the time of the request. 

Bootstrapping a single connection can take up to 20 seconds over a slow wire.  
When one of our customers tried to view data on 7 connections, the application 
(unsurprisingly) timed out.  To address this, we are taking a two-pronged 
approach:
  1.. bootstrap all connections prior to login of the first user (at 
app_start); and

  2.. at bootstrap, create the session factories for each connection in a 
multi-threaded environment to reduce the timeout problem.


The second approach is proving to be problematic.  When calling 
BuildSessionFactory in a multi-threaded environment, the logs show that the 
factories are being constructed serially.  (i.e. I spin off the threads at time 
A, and they come back at times B, B+10, B+20, B+30, etc).  Another developer 
reporting setting up an integration environment to test this, and received a 
duplicate key exception from within NHIbernate.  I have not yet had time to 
review that error or his code, but it points to something problematic with 
using nHibernate in a multi-threaded environment.

Would somebody mind taking a look at the following code and commenting on our 
approach?  Thanks very much.

        public void ConstructSessionFactories(IEnumerable<string> 
connectionNames)         {             var maps = connectionMap.Map.Where(m => 
connectionNames.Contains(m.Key)).Select(m => m.Value);             
maps.ForEach(info =>                 {                     if 
(factoryMap.ContainsKey(info.ConnectionString)) return;                     
WaitForCompletionIfFactoryUnderConstruction(info.ConnectionString);             
        if (factoryMap.ContainsKey(info.ConnectionString)) return;              
       var task = new Task(() => CreateNewFactory(info));                     
task.ContinueWith(FactoryConstructed, 
TaskContinuationOptions.OnlyOnRanToCompletion);                     
task.ContinueWith(FactoryNotConstructed, 
TaskContinuationOptions.NotOnRanToCompletion);                     
task.ContinueWith(FactoryConstructionCausedError, 
TaskContinuationOptions.OnlyOnFaulted);                     
factoriesUnderConstruction[info.ConnectionString] = task;                     
task.Start();                                      });         }        
protected virtual ISessionFactory CreateNewFactory(ConnectionElement info)      
   {             if (factoryMap.ContainsKey(info.ConnectionString)) return 
factoryMap[info.ConnectionString];             logger.DebugFormat("Creating new 
SessionFactory for connection '{0}'", info.Name);             var cfg = 
configurationProvider.Get(info);             ExposeConfiguration(cfg);          
   configData.AddOrUpdate(info.Name, cfg, (key, oldValue) => cfg);             
var factory = cfg.BuildSessionFactory();             
factoryMap[info.ConnectionString] = factory;             return factory;        
 }        private void WaitForCompletionIfFactoryUnderConstruction(string 
connection)         {             while 
(factoriesUnderConstruction.ContainsKey(connection))             {              
   Task task;                 
factoriesUnderConstruction.TryGetValue(connection, out task);                 
if (task != null) task.Wait();             }                     }-- 
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/nhusers?hl=en-US.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

-- 
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/nhusers?hl=en-US.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to