Thanks for the input.

We have one factory per connection string.  The repeated calls to 
factoryMap.ContainsKey are more of a "belt and suspender" approach, with 
the WaitForCompletion... method acting as a sentinel to prevent multiple 
threads trying to create a factory simultaneously.  (Subsequent calls will 
find the connection in the factory map and therefore not try to create a 
new one).

On Wednesday, May 29, 2013 9:39:38 AM UTC-5, PeteA wrote:
>
> The first thing that strikes me is that you're mixing the Task API with 
> some non-thread-safe dictionary operations (WaitForCompletionIf….) - the 
> repeated calls factoryMap.ContainsKey feel like an attempt to mitigate this?
>
>  
>
> My reading is that you're aiming to create one ISessionFactory per 
> connection string, but potentially have many different instances of the 
> same connection string with different names; am I reading this right?  If 
> this is the case then how about flattening the connectionMap into a 
> sequence of distinct connection strings together with the 1st 'map' for 
> each one so that you don't have to worry about duplicates, e.g.
>
>  
>
>                      IEnumerable<KeyValuePair<string, ConnectionElement>> 
> oneMapPerConnectionString = connectionMap.Map.Join(connectionNames, map => 
> map.Key, name => name, (map, name) => map)
>
>                            .GroupBy(map => map.Key)
>
>                            .Select(group => group.First());
>
>  
>
> That should remove the need for any mutices *except* the final addition to 
> factoryMap (in case you happen to get a hash-code clash - bad things would 
> happen if this weren't serialised)
>
>  
>
> /Pete
>
>  
>
> *From:* [email protected] <javascript:> [mailto:
> [email protected] <javascript:>] *On Behalf Of *Kerry
> *Sent:* 29 May 2013 14:48
> *To:* [email protected] <javascript:>
> *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] <javascript:>.
> To post to this group, send email to [email protected] <javascript:>
> .
> 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