diff --git a/src/NHibernate/Async/Loader/Loader.cs b/src/NHibernate/Async/Loader/Loader.cs index 0167ee2ad08..cc0dadf80b8 100644 --- a/src/NHibernate/Async/Loader/Loader.cs +++ b/src/NHibernate/Async/Loader/Loader.cs @@ -10,6 +10,7 @@ using System; using System.Collections; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Data; using System.Data.Common; diff --git a/src/NHibernate/Loader/Loader.cs b/src/NHibernate/Loader/Loader.cs index 13bb38cdfe3..0882e0168f9 100644 --- a/src/NHibernate/Loader/Loader.cs +++ b/src/NHibernate/Loader/Loader.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Data; using System.Data.Common; @@ -31,17 +32,21 @@ namespace NHibernate.Loader /// Abstract superclass of object loading (and querying) strategies. /// /// - ///

+ /// /// This class implements useful common functionality that concrete loaders would delegate to. /// It is not intended that this functionality would be directly accessed by client code (Hence, /// all methods of this class are declared protected or private.) This class relies heavily upon the - /// interface, which is the contract between this class and + /// interface, which is the contract between this class and /// s that may be loaded by it. - ///

- ///

- /// The present implementation is able to load any number of columns of entities and at most + /// + /// + /// The present implementation is able to load any number of columns of entities and at most /// one collection role per query. - ///

+ /// + /// + /// All this class members are thread safe. Entity and collection loaders are held in persisters shared among + /// sessions built from the same session factory. They must be thread safe. + /// ///
/// public abstract partial class Loader @@ -63,8 +68,8 @@ public abstract partial class Loader /// /// Caches subclass entity aliases for given persister index in and subclass entity name /// - private readonly Dictionary, string[][]> _subclassEntityAliasesMap = new Dictionary, string[][]>(); - + private readonly ConcurrentDictionary, string[][]> _subclassEntityAliasesMap = new ConcurrentDictionary, string[][]>(); + protected Loader(ISessionFactoryImplementor factory) { _factory = factory; @@ -1103,14 +1108,9 @@ private void LoadFromResultSet(DbDataReader rs, int i, object obj, string instan private string[][] GetSubclassEntityAliases(int i, ILoadable persister) { var cacheKey = System.Tuple.Create(i, persister.EntityName); - if (_subclassEntityAliasesMap.TryGetValue(cacheKey, out string[][] cols)) - { - return cols; - } - - cols = EntityAliases[i].GetSuffixedPropertyAliases(persister); - _subclassEntityAliasesMap[cacheKey] = cols; - return cols; + return _subclassEntityAliasesMap.GetOrAdd( + cacheKey, + k => EntityAliases[i].GetSuffixedPropertyAliases(persister)); } ///