diff --git a/src/NHibernate/Async/Loader/Loader.cs b/src/NHibernate/Async/Loader/Loader.cs index a3635924cbd..e7e4c333e06 100644 --- a/src/NHibernate/Async/Loader/Loader.cs +++ b/src/NHibernate/Async/Loader/Loader.cs @@ -740,9 +740,7 @@ private async Task InstanceAlreadyLoadedAsync(DbDataReader rs, int i, ILoadable return; } - var instanceClass = await (GetInstanceClassAsync(rs, i, persister, key.Identifier, session, cancellationToken)).ConfigureAwait(false); - entry = entry ?? session.PersistenceContext.GetEntry(obj); - await (UpdateLazyPropertiesFromResultSetAsync(rs, i, obj, instanceClass, key, entry, persister, session, cacheBatchingHandler, cancellationToken)).ConfigureAwait(false); + await (UpdateLazyPropertiesFromResultSetAsync(rs, i, obj, key, entry, persister, session, cacheBatchingHandler, cancellationToken)).ConfigureAwait(false); } /// @@ -755,7 +753,7 @@ private async Task InstanceNotYetLoadedAsync(DbDataReader dr, int i, ILo cancellationToken.ThrowIfCancellationRequested(); object obj; - string instanceClass = await (GetInstanceClassAsync(dr, i, persister, key.Identifier, session, cancellationToken)).ConfigureAwait(false); + ILoadable concretePersister = await (GetConcretePersisterAsync(dr, i, persister, key.Identifier, session, cancellationToken)).ConfigureAwait(false); if (optionalObjectKey != null && key.Equals(optionalObjectKey)) { @@ -764,7 +762,7 @@ private async Task InstanceNotYetLoadedAsync(DbDataReader dr, int i, ILo } else { - obj = session.Instantiate(instanceClass, key.Identifier); + obj = session.Instantiate(concretePersister, key.Identifier); } // need to hydrate it @@ -773,7 +771,7 @@ private async Task InstanceNotYetLoadedAsync(DbDataReader dr, int i, ILo // (but don't yet initialize the object itself) // note that we acquired LockMode.READ even if it was not requested LockMode acquiredLockMode = lockMode == LockMode.None ? LockMode.Read : lockMode; - await (LoadFromResultSetAsync(dr, i, obj, instanceClass, key, acquiredLockMode, persister, session, cancellationToken)).ConfigureAwait(false); + await (LoadFromResultSetAsync(dr, i, obj, concretePersister, key, acquiredLockMode, persister, session, cancellationToken)).ConfigureAwait(false); // materialize associations (and initialize the object) later hydratedObjects.Add(obj); @@ -781,8 +779,8 @@ private async Task InstanceNotYetLoadedAsync(DbDataReader dr, int i, ILo return obj; } - private async Task UpdateLazyPropertiesFromResultSetAsync(DbDataReader rs, int i, object obj, string instanceClass, EntityKey key, - EntityEntry entry, ILoadable rootPersister, ISessionImplementor session, + private async Task UpdateLazyPropertiesFromResultSetAsync(DbDataReader rs, int i, object obj, EntityKey key, + EntityEntry optionalEntry, ILoadable rootPersister, ISessionImplementor session, Action cacheBatchingHandler, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -794,11 +792,8 @@ private async Task UpdateLazyPropertiesFromResultSetAsync(DbDataReader rs, int i return; // No lazy properties were loaded } - // Get the persister for the _subclass_ - var persister = instanceClass == rootPersister.EntityName - ? rootPersister - : (ILoadable) Factory.GetEntityPersister(instanceClass); - + var persister = await (GetConcretePersisterAsync(rs, i, rootPersister, key.Identifier, session, cancellationToken)).ConfigureAwait(false); + var entry = optionalEntry ?? session.PersistenceContext.GetEntry(obj); // The property values will not be set when the entry status is Loading so in that case we have to get // the uninitialized lazy properties from the loaded state var uninitializedProperties = entry.Status == Status.Loading @@ -822,7 +817,7 @@ private async Task UpdateLazyPropertiesFromResultSetAsync(DbDataReader rs, int i ? EntityAliases[i].SuffixedPropertyAliases : GetSubclassEntityAliases(i, persister); - if (!await (persister.InitializeLazyPropertiesAsync(rs, id, obj, rootPersister, cols, updateLazyProperties, fetchAllProperties, session, cancellationToken)).ConfigureAwait(false)) + if (!await (persister.InitializeLazyPropertiesAsync(rs, id, obj, cols, updateLazyProperties, fetchAllProperties, session, cancellationToken)).ConfigureAwait(false)) { return; } @@ -882,18 +877,13 @@ internal static async Task UpdateCacheForEntityAsync( /// an array of "hydrated" values (do not resolve associations yet), /// and pass the hydrated state to the session. /// - private async Task LoadFromResultSetAsync(DbDataReader rs, int i, object obj, string instanceClass, EntityKey key, + private async Task LoadFromResultSetAsync(DbDataReader rs, int i, object obj, ILoadable persister, EntityKey key, LockMode lockMode, ILoadable rootPersister, ISessionImplementor session, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); object id = key.Identifier; - // Get the persister for the _subclass_ - ILoadable persister = instanceClass == rootPersister.EntityName - ? rootPersister - : (ILoadable) Factory.GetEntityPersister(instanceClass); - if (Log.IsDebugEnabled()) { Log.Debug("Initializing object from DataReader: {0}", MessageHelper.InfoString(persister, id)); @@ -921,7 +911,7 @@ private async Task LoadFromResultSetAsync(DbDataReader rs, int i, object obj, st /// /// Determine the concrete class of an instance for the DbDataReader /// - private async Task GetInstanceClassAsync(DbDataReader rs, int i, ILoadable persister, object id, ISessionImplementor session, CancellationToken cancellationToken) + private async Task GetConcretePersisterAsync(DbDataReader rs, int i, ILoadable persister, object id, ISessionImplementor session, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (persister.HasSubclasses) @@ -939,9 +929,11 @@ private async Task GetInstanceClassAsync(DbDataReader rs, int i, ILoadab persister.EntityName); } - return result; + return persister.EntityName == result + ? persister + : (ILoadable) Factory.GetEntityPersister(result); } - return persister.EntityName; + return persister; } /// diff --git a/src/NHibernate/Async/Persister/Entity/AbstractEntityPersister.cs b/src/NHibernate/Async/Persister/Entity/AbstractEntityPersister.cs index 43d5f59da49..ff5580194f5 100644 --- a/src/NHibernate/Async/Persister/Entity/AbstractEntityPersister.cs +++ b/src/NHibernate/Async/Persister/Entity/AbstractEntityPersister.cs @@ -62,7 +62,7 @@ public virtual Task BindValuesAsync(DbCommand ps, CancellationToken cancellation } public Task InitializeLazyPropertiesAsync( - DbDataReader rs, object id, object entity, ILoadable rootPersister, string[][] suffixedPropertyColumns, + DbDataReader rs, object id, object entity, string[][] suffixedPropertyColumns, string[] uninitializedLazyProperties, bool allLazyProperties, ISessionImplementor session, CancellationToken cancellationToken) { if (!HasLazyProperties) diff --git a/src/NHibernate/Async/Persister/Entity/ILoadable.cs b/src/NHibernate/Async/Persister/Entity/ILoadable.cs index 8d164a06685..08729f3ad44 100644 --- a/src/NHibernate/Async/Persister/Entity/ILoadable.cs +++ b/src/NHibernate/Async/Persister/Entity/ILoadable.cs @@ -73,7 +73,7 @@ public static Task HydrateAsync( /// //6.0 TODO: Change to void and merge into ILoadable internal static async Task InitializeLazyPropertiesAsync( - this ILoadable loadable, DbDataReader rs, object id, object entity, ILoadable rootPersister, string[][] suffixedPropertyColumns, + this ILoadable loadable, DbDataReader rs, object id, object entity, string[][] suffixedPropertyColumns, string[] uninitializedLazyProperties, bool allLazyProperties, ISessionImplementor session, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -83,7 +83,6 @@ internal static async Task InitializeLazyPropertiesAsync( rs, id, entity, - rootPersister, suffixedPropertyColumns, uninitializedLazyProperties, allLazyProperties, diff --git a/src/NHibernate/Engine/ISessionImplementor.cs b/src/NHibernate/Engine/ISessionImplementor.cs index 5659e418f09..84b30da88ae 100644 --- a/src/NHibernate/Engine/ISessionImplementor.cs +++ b/src/NHibernate/Engine/ISessionImplementor.cs @@ -21,6 +21,16 @@ namespace NHibernate.Engine // 6.0 TODO: Convert to interface methods, excepted SwitchCacheMode internal static partial class SessionImplementorExtensions { + /// + /// Instantiate the entity class, initializing with the given identifier + /// + internal static object Instantiate(this ISessionImplementor session, IEntityPersister persister, object id) + { + if(session is AbstractSessionImpl impl) + return impl.Instantiate(persister, id); + return session.Instantiate(persister.EntityName, id); + } + internal static IDisposable BeginContext(this ISessionImplementor session) { if (session == null) @@ -249,6 +259,8 @@ public partial interface ISessionImplementor /// object GetContextEntityIdentifier(object obj); + //Since 5.3 + //TODO 6.0 Remove (see SessionImplementorExtensions.Instantiate for replacement) /// /// Instantiate the entity class, initializing with the given identifier /// diff --git a/src/NHibernate/Event/IEventSource.cs b/src/NHibernate/Event/IEventSource.cs index 423415d9f1a..5f5c0d42090 100644 --- a/src/NHibernate/Event/IEventSource.cs +++ b/src/NHibernate/Event/IEventSource.cs @@ -16,6 +16,7 @@ public partial interface IEventSource : ISessionImplementor, ISession /// bool AutoFlushSuspended { get; } + //6.0 TODO Remove it (it's added directly to ISessionImplementor) /// /// Instantiate an entity instance, using either an interceptor, /// or the given persister diff --git a/src/NHibernate/Impl/AbstractSessionImpl.cs b/src/NHibernate/Impl/AbstractSessionImpl.cs index b5c9ada3626..173a8cba7bd 100644 --- a/src/NHibernate/Impl/AbstractSessionImpl.cs +++ b/src/NHibernate/Impl/AbstractSessionImpl.cs @@ -192,8 +192,19 @@ public IList ListFilter(object collection, IQueryExpression queryExpression, Que public abstract void FlushBeforeTransactionCompletion(); public abstract void AfterTransactionCompletion(bool successful, ITransaction tx); public abstract object GetContextEntityIdentifier(object obj); + + //Since 5.3 + [Obsolete("Use override with persister parameter")] public abstract object Instantiate(string clazz, object id); + //6.0 TODO: Make abstract + public virtual object Instantiate(IEntityPersister persister, object id) + { +#pragma warning disable 618 + return Instantiate(persister.EntityName, id); +#pragma warning restore 618 + } + public virtual IList List(NativeSQLQuerySpecification spec, QueryParameters queryParameters) { using (BeginProcess()) diff --git a/src/NHibernate/Impl/SessionImpl.cs b/src/NHibernate/Impl/SessionImpl.cs index d319e08ae7d..1718f879a16 100644 --- a/src/NHibernate/Impl/SessionImpl.cs +++ b/src/NHibernate/Impl/SessionImpl.cs @@ -761,6 +761,8 @@ private IQueryExpressionPlan GetFilterQueryPlan(string role, bool shallow, strin : Factory.QueryPlanCache.GetFilterQueryPlan(filter, role, shallow, EnabledFilters); } + //Since 5.3 + [Obsolete("Use override with persister parameter")] public override object Instantiate(string clazz, object id) { using (BeginProcess()) @@ -785,7 +787,7 @@ public ActionQueue ActionQueue /// /// /// - public object Instantiate(IEntityPersister persister, object id) + public override object Instantiate(IEntityPersister persister, object id) { using (BeginProcess()) { diff --git a/src/NHibernate/Impl/StatelessSessionImpl.cs b/src/NHibernate/Impl/StatelessSessionImpl.cs index 479d37c6ef4..4eb3630391e 100644 --- a/src/NHibernate/Impl/StatelessSessionImpl.cs +++ b/src/NHibernate/Impl/StatelessSessionImpl.cs @@ -244,11 +244,18 @@ public override object GetContextEntityIdentifier(object obj) } } + //Since 5.3 + [Obsolete("Use override with persister parameter")] public override object Instantiate(string clazz, object id) + { + return Instantiate(Factory.GetEntityPersister(clazz), id); + } + + public override object Instantiate(IEntityPersister persister, object id) { using (BeginProcess()) { - return Factory.GetEntityPersister(clazz).Instantiate(id); + return persister.Instantiate(id); } } diff --git a/src/NHibernate/Loader/Loader.cs b/src/NHibernate/Loader/Loader.cs index d99e99c8695..1bc8baaa9e4 100644 --- a/src/NHibernate/Loader/Loader.cs +++ b/src/NHibernate/Loader/Loader.cs @@ -1070,9 +1070,7 @@ private void InstanceAlreadyLoaded(DbDataReader rs, int i, ILoadable persister, return; } - var instanceClass = GetInstanceClass(rs, i, persister, key.Identifier, session); - entry = entry ?? session.PersistenceContext.GetEntry(obj); - UpdateLazyPropertiesFromResultSet(rs, i, obj, instanceClass, key, entry, persister, session, cacheBatchingHandler); + UpdateLazyPropertiesFromResultSet(rs, i, obj, key, entry, persister, session, cacheBatchingHandler); } private void CacheByUniqueKey(int i, IEntityPersister persister, object obj, ISessionImplementor session, bool alreadyLoaded) @@ -1116,7 +1114,7 @@ private object InstanceNotYetLoaded(DbDataReader dr, int i, ILoadable persister, { object obj; - string instanceClass = GetInstanceClass(dr, i, persister, key.Identifier, session); + ILoadable concretePersister = GetConcretePersister(dr, i, persister, key.Identifier, session); if (optionalObjectKey != null && key.Equals(optionalObjectKey)) { @@ -1125,7 +1123,7 @@ private object InstanceNotYetLoaded(DbDataReader dr, int i, ILoadable persister, } else { - obj = session.Instantiate(instanceClass, key.Identifier); + obj = session.Instantiate(concretePersister, key.Identifier); } // need to hydrate it @@ -1134,7 +1132,7 @@ private object InstanceNotYetLoaded(DbDataReader dr, int i, ILoadable persister, // (but don't yet initialize the object itself) // note that we acquired LockMode.READ even if it was not requested LockMode acquiredLockMode = lockMode == LockMode.None ? LockMode.Read : lockMode; - LoadFromResultSet(dr, i, obj, instanceClass, key, acquiredLockMode, persister, session); + LoadFromResultSet(dr, i, obj, concretePersister, key, acquiredLockMode, persister, session); // materialize associations (and initialize the object) later hydratedObjects.Add(obj); @@ -1159,8 +1157,8 @@ private HashSet GetFetchLazyProperties(int i) return array?[i]; } - private void UpdateLazyPropertiesFromResultSet(DbDataReader rs, int i, object obj, string instanceClass, EntityKey key, - EntityEntry entry, ILoadable rootPersister, ISessionImplementor session, + private void UpdateLazyPropertiesFromResultSet(DbDataReader rs, int i, object obj, EntityKey key, + EntityEntry optionalEntry, ILoadable rootPersister, ISessionImplementor session, Action cacheBatchingHandler) { var fetchAllProperties = IsEagerPropertyFetchEnabled(i); @@ -1171,11 +1169,8 @@ private void UpdateLazyPropertiesFromResultSet(DbDataReader rs, int i, object ob return; // No lazy properties were loaded } - // Get the persister for the _subclass_ - var persister = instanceClass == rootPersister.EntityName - ? rootPersister - : (ILoadable) Factory.GetEntityPersister(instanceClass); - + var persister = GetConcretePersister(rs, i, rootPersister, key.Identifier, session); + var entry = optionalEntry ?? session.PersistenceContext.GetEntry(obj); // The property values will not be set when the entry status is Loading so in that case we have to get // the uninitialized lazy properties from the loaded state var uninitializedProperties = entry.Status == Status.Loading @@ -1199,7 +1194,7 @@ private void UpdateLazyPropertiesFromResultSet(DbDataReader rs, int i, object ob ? EntityAliases[i].SuffixedPropertyAliases : GetSubclassEntityAliases(i, persister); - if (!persister.InitializeLazyProperties(rs, id, obj, rootPersister, cols, updateLazyProperties, fetchAllProperties, session)) + if (!persister.InitializeLazyProperties(rs, id, obj, cols, updateLazyProperties, fetchAllProperties, session)) { return; } @@ -1258,17 +1253,12 @@ internal static void UpdateCacheForEntity( /// an array of "hydrated" values (do not resolve associations yet), /// and pass the hydrated state to the session. /// - private void LoadFromResultSet(DbDataReader rs, int i, object obj, string instanceClass, EntityKey key, + private void LoadFromResultSet(DbDataReader rs, int i, object obj, ILoadable persister, EntityKey key, LockMode lockMode, ILoadable rootPersister, ISessionImplementor session) { object id = key.Identifier; - // Get the persister for the _subclass_ - ILoadable persister = instanceClass == rootPersister.EntityName - ? rootPersister - : (ILoadable) Factory.GetEntityPersister(instanceClass); - if (Log.IsDebugEnabled()) { Log.Debug("Initializing object from DataReader: {0}", MessageHelper.InfoString(persister, id)); @@ -1304,7 +1294,7 @@ private string[][] GetSubclassEntityAliases(int i, ILoadable persister) /// /// Determine the concrete class of an instance for the DbDataReader /// - private string GetInstanceClass(DbDataReader rs, int i, ILoadable persister, object id, ISessionImplementor session) + private ILoadable GetConcretePersister(DbDataReader rs, int i, ILoadable persister, object id, ISessionImplementor session) { if (persister.HasSubclasses) { @@ -1321,9 +1311,11 @@ private string GetInstanceClass(DbDataReader rs, int i, ILoadable persister, obj persister.EntityName); } - return result; + return persister.EntityName == result + ? persister + : (ILoadable) Factory.GetEntityPersister(result); } - return persister.EntityName; + return persister; } /// diff --git a/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs b/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs index ef644bba041..b2d8abd92c3 100644 --- a/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs +++ b/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs @@ -1395,7 +1395,7 @@ public virtual object InitializeLazyProperty(string fieldName, object entity, IS } public void InitializeLazyProperties( - DbDataReader rs, object id, object entity, ILoadable rootPersister, string[][] suffixedPropertyColumns, + DbDataReader rs, object id, object entity, string[][] suffixedPropertyColumns, string[] uninitializedLazyProperties, bool allLazyProperties, ISessionImplementor session) { if (!HasLazyProperties) diff --git a/src/NHibernate/Persister/Entity/ILoadable.cs b/src/NHibernate/Persister/Entity/ILoadable.cs index 992463e0e33..3b20e1baf33 100644 --- a/src/NHibernate/Persister/Entity/ILoadable.cs +++ b/src/NHibernate/Persister/Entity/ILoadable.cs @@ -107,7 +107,7 @@ public static object[] Hydrate( /// //6.0 TODO: Change to void and merge into ILoadable internal static bool InitializeLazyProperties( - this ILoadable loadable, DbDataReader rs, object id, object entity, ILoadable rootPersister, string[][] suffixedPropertyColumns, + this ILoadable loadable, DbDataReader rs, object id, object entity, string[][] suffixedPropertyColumns, string[] uninitializedLazyProperties, bool allLazyProperties, ISessionImplementor session) { if (loadable is AbstractEntityPersister abstractEntityPersister) @@ -116,7 +116,6 @@ internal static bool InitializeLazyProperties( rs, id, entity, - rootPersister, suffixedPropertyColumns, uninitializedLazyProperties, allLazyProperties,