Skip to content

Eliminated double Persister resolution in Loader.InstanceNotYetLoaded flow #476

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Mar 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 15 additions & 23 deletions src/NHibernate/Async/Loader/Loader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/// <summary>
Expand All @@ -755,7 +753,7 @@ private async Task<object> 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))
{
Expand All @@ -764,7 +762,7 @@ private async Task<object> InstanceNotYetLoadedAsync(DbDataReader dr, int i, ILo
}
else
{
obj = session.Instantiate(instanceClass, key.Identifier);
obj = session.Instantiate(concretePersister, key.Identifier);
}

// need to hydrate it
Expand All @@ -773,16 +771,16 @@ private async Task<object> 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);

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<IEntityPersister, CachePutData> cacheBatchingHandler, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
Expand All @@ -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
Expand All @@ -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;
}
Expand Down Expand Up @@ -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.
/// </summary>
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));
Expand Down Expand Up @@ -921,7 +911,7 @@ private async Task LoadFromResultSetAsync(DbDataReader rs, int i, object obj, st
/// <summary>
/// Determine the concrete class of an instance for the <c>DbDataReader</c>
/// </summary>
private async Task<string> GetInstanceClassAsync(DbDataReader rs, int i, ILoadable persister, object id, ISessionImplementor session, CancellationToken cancellationToken)
private async Task<ILoadable> GetConcretePersisterAsync(DbDataReader rs, int i, ILoadable persister, object id, ISessionImplementor session, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if (persister.HasSubclasses)
Expand All @@ -939,9 +929,11 @@ private async Task<string> GetInstanceClassAsync(DbDataReader rs, int i, ILoadab
persister.EntityName);
}

return result;
return persister.EntityName == result
? persister
: (ILoadable) Factory.GetEntityPersister(result);
}
return persister.EntityName;
return persister;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 1 addition & 2 deletions src/NHibernate/Async/Persister/Entity/ILoadable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public static Task<object[]> HydrateAsync(
/// </summary>
//6.0 TODO: Change to void and merge into ILoadable
internal static async Task<bool> 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();
Expand All @@ -83,7 +83,6 @@ internal static async Task<bool> InitializeLazyPropertiesAsync(
rs,
id,
entity,
rootPersister,
suffixedPropertyColumns,
uninitializedLazyProperties,
allLazyProperties,
Expand Down
12 changes: 12 additions & 0 deletions src/NHibernate/Engine/ISessionImplementor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ namespace NHibernate.Engine
// 6.0 TODO: Convert to interface methods, excepted SwitchCacheMode
internal static partial class SessionImplementorExtensions
{
/// <summary>
/// Instantiate the entity class, initializing with the given identifier
/// </summary>
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)
Expand Down Expand Up @@ -249,6 +259,8 @@ public partial interface ISessionImplementor
/// </summary>
object GetContextEntityIdentifier(object obj);

//Since 5.3
//TODO 6.0 Remove (see SessionImplementorExtensions.Instantiate for replacement)
/// <summary>
/// Instantiate the entity class, initializing with the given identifier
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions src/NHibernate/Event/IEventSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public partial interface IEventSource : ISessionImplementor, ISession
/// </summary>
bool AutoFlushSuspended { get; }

//6.0 TODO Remove it (it's added directly to ISessionImplementor)
/// <summary>
/// Instantiate an entity instance, using either an interceptor,
/// or the given persister
Expand Down
11 changes: 11 additions & 0 deletions src/NHibernate/Impl/AbstractSessionImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
4 changes: 3 additions & 1 deletion src/NHibernate/Impl/SessionImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand All @@ -785,7 +787,7 @@ public ActionQueue ActionQueue
/// <param name="persister"></param>
/// <param name="id"></param>
/// <returns></returns>
public object Instantiate(IEntityPersister persister, object id)
public override object Instantiate(IEntityPersister persister, object id)
{
using (BeginProcess())
{
Expand Down
9 changes: 8 additions & 1 deletion src/NHibernate/Impl/StatelessSessionImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
38 changes: 15 additions & 23 deletions src/NHibernate/Loader/Loader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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))
{
Expand All @@ -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
Expand All @@ -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);
Expand All @@ -1159,8 +1157,8 @@ private HashSet<string> 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<IEntityPersister, CachePutData> cacheBatchingHandler)
{
var fetchAllProperties = IsEagerPropertyFetchEnabled(i);
Expand All @@ -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
Expand All @@ -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;
}
Expand Down Expand Up @@ -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.
/// </summary>
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));
Expand Down Expand Up @@ -1304,7 +1294,7 @@ private string[][] GetSubclassEntityAliases(int i, ILoadable persister)
/// <summary>
/// Determine the concrete class of an instance for the <c>DbDataReader</c>
/// </summary>
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)
{
Expand All @@ -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;
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate/Persister/Entity/AbstractEntityPersister.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 1 addition & 2 deletions src/NHibernate/Persister/Entity/ILoadable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public static object[] Hydrate(
/// </summary>
//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)
Expand All @@ -116,7 +116,6 @@ internal static bool InitializeLazyProperties(
rs,
id,
entity,
rootPersister,
suffixedPropertyColumns,
uninitializedLazyProperties,
allLazyProperties,
Expand Down