diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH1439/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH1439/Fixture.cs
index 0962d06c353..cf61e951e2d 100644
--- a/src/NHibernate.Test/Async/NHSpecificTest/GH1439/Fixture.cs
+++ b/src/NHibernate.Test/Async/NHSpecificTest/GH1439/Fixture.cs
@@ -91,7 +91,7 @@ public async Task LazyPropertyShouldBeUninitializedAndLoadableAsync()
Is.False,
"Lazy property initialization status");
Assert.That(
- FieldInterceptionHelper.IsInstrumented(e1),
+ e1 is IFieldInterceptorAccessor,
Is.True,
"Entity IsInstrumented");
Assert.That(
@@ -117,7 +117,7 @@ public async Task LazyPropertyShouldBeUninitializedAndLoadableWithComponentIdAsy
Is.False,
"Lazy property initialization status");
Assert.That(
- FieldInterceptionHelper.IsInstrumented(e2),
+ e2 is IFieldInterceptorAccessor,
Is.True,
"Entity IsInstrumented");
Assert.That(
diff --git a/src/NHibernate.Test/NHSpecificTest/GH1439/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH1439/Fixture.cs
index 5a12bfe77fe..d77e02a0fae 100644
--- a/src/NHibernate.Test/NHSpecificTest/GH1439/Fixture.cs
+++ b/src/NHibernate.Test/NHSpecificTest/GH1439/Fixture.cs
@@ -79,7 +79,7 @@ public void LazyPropertyShouldBeUninitializedAndLoadable()
Is.False,
"Lazy property initialization status");
Assert.That(
- FieldInterceptionHelper.IsInstrumented(e1),
+ e1 is IFieldInterceptorAccessor,
Is.True,
"Entity IsInstrumented");
Assert.That(
@@ -105,7 +105,7 @@ public void LazyPropertyShouldBeUninitializedAndLoadableWithComponentId()
Is.False,
"Lazy property initialization status");
Assert.That(
- FieldInterceptionHelper.IsInstrumented(e2),
+ e2 is IFieldInterceptorAccessor,
Is.True,
"Entity IsInstrumented");
Assert.That(
diff --git a/src/NHibernate/Async/Engine/Cascade.cs b/src/NHibernate/Async/Engine/Cascade.cs
index e33a941ba1e..77e8b93bfb1 100644
--- a/src/NHibernate/Async/Engine/Cascade.cs
+++ b/src/NHibernate/Async/Engine/Cascade.cs
@@ -60,7 +60,7 @@ public async Task CascadeOnAsync(IEntityPersister persister, object parent, obje
IType[] types = persister.PropertyTypes;
CascadeStyle[] cascadeStyles = persister.PropertyCascadeStyles;
- var uninitializedLazyProperties = persister.GetUninitializedLazyProperties(parent);
+ var uninitializedLazyProperties = persister.EntityMetamodel.BytecodeEnhancementMetadata.GetUninitializedLazyProperties(parent);
for (int i = 0; i < types.Length; i++)
{
CascadeStyle style = cascadeStyles[i];
diff --git a/src/NHibernate/Async/Event/Default/DefaultMergeEventListener.cs b/src/NHibernate/Async/Event/Default/DefaultMergeEventListener.cs
index 40848b4f356..9384b786b79 100644
--- a/src/NHibernate/Async/Event/Default/DefaultMergeEventListener.cs
+++ b/src/NHibernate/Async/Event/Default/DefaultMergeEventListener.cs
@@ -389,7 +389,7 @@ protected virtual async Task EntityIsDetachedAsync(MergeEvent @event, IDictionar
await (CopyValuesAsync(persister, entity, target, source, copyCache, cancellationToken)).ConfigureAwait(false);
//copyValues works by reflection, so explicitly mark the entity instance dirty
- MarkInterceptorDirty(entity, target);
+ MarkInterceptorDirty(entity, persister, target);
@event.Result = result;
}
diff --git a/src/NHibernate/Async/Persister/Entity/AbstractEntityPersister.cs b/src/NHibernate/Async/Persister/Entity/AbstractEntityPersister.cs
index d2d0a5e3361..ae54caf3fcb 100644
--- a/src/NHibernate/Async/Persister/Entity/AbstractEntityPersister.cs
+++ b/src/NHibernate/Async/Persister/Entity/AbstractEntityPersister.cs
@@ -36,6 +36,7 @@
using Property=NHibernate.Mapping.Property;
using NHibernate.SqlTypes;
using System.Linq;
+using NHibernate.Bytecode;
namespace NHibernate.Persister.Entity
{
diff --git a/src/NHibernate/Bytecode/IBytecodeEnhancementMetadata.cs b/src/NHibernate/Bytecode/IBytecodeEnhancementMetadata.cs
new file mode 100644
index 00000000000..df7f58e4fd5
--- /dev/null
+++ b/src/NHibernate/Bytecode/IBytecodeEnhancementMetadata.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NHibernate.Engine;
+using NHibernate.Intercept;
+using NHibernate.Tuple.Entity;
+
+namespace NHibernate.Bytecode
+{
+ ///
+ /// Encapsulates bytecode enhancement information about a particular entity.
+ ///
+ /// Author: Steve Ebersole
+ ///
+ public interface IBytecodeEnhancementMetadata
+ {
+ ///
+ /// The name of the entity to which this metadata applies.
+ ///
+ string EntityName { get; }
+
+ ///
+ /// Has the entity class been bytecode enhanced for lazy loading?
+ ///
+ bool EnhancedForLazyLoading { get; }
+
+ ///
+ /// Has the information about all lazy properties
+ ///
+ LazyPropertiesMetadata LazyPropertiesMetadata { get; }
+
+ ///
+ /// Has the information about all properties mapped as lazy="no-proxy"
+ ///
+ UnwrapProxyPropertiesMetadata UnwrapProxyPropertiesMetadata { get; }
+
+ ///
+ /// Build and inject an interceptor instance into the enhanced entity.
+ ///
+ /// The entity into which built interceptor should be injected.
+ /// Whether all lazy properties were unfetched or not.
+ /// The session to which the entity instance belongs.
+ /// The built and injected interceptor.
+ // TODO: Remove lazyPropertiesAreUnfetched when interceptor will be injected on entity instantiation
+ IFieldInterceptor InjectInterceptor(object entity, bool lazyPropertiesAreUnfetched, ISessionImplementor session);
+
+ ///
+ /// Extract the field interceptor instance from the enhanced entity.
+ ///
+ /// The entity from which to extract the interceptor.
+ /// The extracted interceptor.
+ IFieldInterceptor ExtractInterceptor(object entity);
+
+ ///
+ /// Retrieve the uninitialized lazy properties from the enhanced entity.
+ ///
+ /// The entity from which to retrieve the uninitialized lazy properties.
+ /// The uninitialized property names.
+ ISet GetUninitializedLazyProperties(object entity);
+
+ ///
+ /// Retrieve the uninitialized lazy properties from the entity state.
+ ///
+ /// The entity state from which to retrieve the uninitialized lazy properties.
+ /// The uninitialized property names.
+ ISet GetUninitializedLazyProperties(object[] entityState);
+ }
+}
diff --git a/src/NHibernate/Bytecode/LazyPropertiesMetadata.cs b/src/NHibernate/Bytecode/LazyPropertiesMetadata.cs
new file mode 100644
index 00000000000..ee70714e9b1
--- /dev/null
+++ b/src/NHibernate/Bytecode/LazyPropertiesMetadata.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Iesi.Collections.Generic;
+using NHibernate.Util;
+
+namespace NHibernate.Bytecode
+{
+ ///
+ /// Information about all of the bytecode lazy properties for an entity
+ ///
+ /// Author: Steve Ebersole
+ ///
+ [Serializable]
+ public class LazyPropertiesMetadata
+ {
+ public static LazyPropertiesMetadata NonEnhanced(string entityName)
+ {
+ return new LazyPropertiesMetadata(entityName, null);
+ }
+
+ public static LazyPropertiesMetadata From(
+ string entityName,
+ IEnumerable lazyPropertyDescriptors)
+ {
+ // TODO: port lazy fetch groups
+ return new LazyPropertiesMetadata(
+ entityName,
+ lazyPropertyDescriptors.ToDictionary(o => o.Name));
+ }
+
+ private readonly IDictionary _lazyPropertyDescriptors;
+
+ public LazyPropertiesMetadata(
+ string entityName,
+ IDictionary lazyPropertyDescriptors)
+ {
+ EntityName = entityName;
+ _lazyPropertyDescriptors = lazyPropertyDescriptors;
+ HasLazyProperties = _lazyPropertyDescriptors?.Count > 0;
+ LazyPropertyNames = HasLazyProperties
+ ? new ReadOnlySet(new HashSet(_lazyPropertyDescriptors.Keys))
+ : CollectionHelper.EmptySet();
+ // TODO: port lazy fetch groups
+ }
+
+ public string EntityName { get; }
+
+ public bool HasLazyProperties { get; }
+
+ public ISet LazyPropertyNames { get; }
+
+ public IEnumerable LazyPropertyDescriptors =>
+ _lazyPropertyDescriptors?.Values ?? Enumerable.Empty();
+ }
+}
diff --git a/src/NHibernate/Bytecode/LazyPropertyDescriptor.cs b/src/NHibernate/Bytecode/LazyPropertyDescriptor.cs
new file mode 100644
index 00000000000..a0640ef9470
--- /dev/null
+++ b/src/NHibernate/Bytecode/LazyPropertyDescriptor.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NHibernate.Type;
+
+namespace NHibernate.Bytecode
+{
+ ///
+ /// Descriptor for a property which is enabled for bytecode lazy fetching
+ ///
+ /// Author: Steve Ebersole
+ ///
+ [Serializable]
+ public class LazyPropertyDescriptor
+ {
+ public static LazyPropertyDescriptor From(
+ Mapping.Property property,
+ int propertyIndex,
+ int lazyIndex)
+ {
+ // TODO: port lazy fetch groups
+
+ return new LazyPropertyDescriptor(
+ propertyIndex,
+ lazyIndex,
+ property.Name,
+ property.Type
+ );
+ }
+
+ private LazyPropertyDescriptor(
+ int propertyIndex,
+ int lazyIndex,
+ string name,
+ IType type)
+ {
+ if (propertyIndex < lazyIndex)
+ {
+ throw new InvalidOperationException("Property index is lower than the lazy index.");
+ }
+
+ PropertyIndex = propertyIndex;
+ LazyIndex = lazyIndex;
+ Name = name;
+ Type = type;
+ }
+
+ ///
+ /// Access to the index of the property in terms of its position in the entity persister
+ ///
+ public int PropertyIndex { get; }
+
+ ///
+ /// Access to the index of the property in terms of its position within the lazy properties of the persister
+ ///
+ public int LazyIndex { get; }
+
+ ///
+ /// Access to the name of the property
+ ///
+ public string Name { get; }
+
+ ///
+ /// Access to the property's type
+ ///
+ public IType Type { get; }
+ }
+}
diff --git a/src/NHibernate/Bytecode/NotInstrumentedException.cs b/src/NHibernate/Bytecode/NotInstrumentedException.cs
new file mode 100644
index 00000000000..71a392b9b0a
--- /dev/null
+++ b/src/NHibernate/Bytecode/NotInstrumentedException.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace NHibernate.Bytecode
+{
+ ///
+ /// Indicates a condition where an instrumented/enhanced class was expected, but the class was not
+ /// instrumented/enhanced.
+ ///
+ /// Author: Steve Ebersole
+ ///
+ [Serializable]
+ public class NotInstrumentedException : HibernateException
+ {
+ ///
+ /// Constructs a NotInstrumentedException.
+ ///
+ /// Message explaining the exception condition.
+ public NotInstrumentedException(string message) : base(message)
+ {
+ }
+
+ ///
+ protected NotInstrumentedException(SerializationInfo info, StreamingContext context)
+ : base(info, context) {}
+ }
+}
diff --git a/src/NHibernate/Bytecode/UnwrapProxyPropertiesMetadata.cs b/src/NHibernate/Bytecode/UnwrapProxyPropertiesMetadata.cs
new file mode 100644
index 00000000000..9c2b6f6111e
--- /dev/null
+++ b/src/NHibernate/Bytecode/UnwrapProxyPropertiesMetadata.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Iesi.Collections.Generic;
+using NHibernate.Util;
+
+namespace NHibernate.Bytecode
+{
+ ///
+ /// Information about all properties mapped as lazy="no-proxy" for an entity
+ ///
+ [Serializable]
+ public class UnwrapProxyPropertiesMetadata
+ {
+ public static UnwrapProxyPropertiesMetadata NonEnhanced(string entityName)
+ {
+ return new UnwrapProxyPropertiesMetadata(entityName, null);
+ }
+
+ public static UnwrapProxyPropertiesMetadata From(
+ string entityName,
+ IEnumerable unwrapProxyPropertyDescriptors)
+ {
+ return new UnwrapProxyPropertiesMetadata(
+ entityName,
+ unwrapProxyPropertyDescriptors.ToDictionary(o => o.Name));
+ }
+
+ private readonly IDictionary _unwrapProxyPropertyDescriptors;
+
+ public UnwrapProxyPropertiesMetadata(
+ string entityName,
+ IDictionary unwrapProxyPropertyDescriptors)
+ {
+ EntityName = entityName;
+ _unwrapProxyPropertyDescriptors = unwrapProxyPropertyDescriptors;
+ HasUnwrapProxyProperties = unwrapProxyPropertyDescriptors?.Count > 0;
+ UnwrapProxyPropertyNames = HasUnwrapProxyProperties
+ ? new ReadOnlySet(new HashSet(unwrapProxyPropertyDescriptors.Keys))
+ : CollectionHelper.EmptySet();
+ }
+
+ public string EntityName { get; }
+
+ public bool HasUnwrapProxyProperties { get; }
+
+ public ISet UnwrapProxyPropertyNames { get; }
+
+ public IEnumerable UnwrapProxyPropertyDescriptors =>
+ _unwrapProxyPropertyDescriptors?.Values ?? Enumerable.Empty();
+
+ public int GetUnwrapProxyPropertyIndex(string propertyName)
+ {
+ if (!_unwrapProxyPropertyDescriptors.TryGetValue(propertyName, out var descriptor))
+ {
+ throw new InvalidOperationException(
+ $"Property {propertyName} is not mapped as lazy=\"no-proxy\" on entity {EntityName}");
+ }
+
+ return descriptor.PropertyIndex;
+ }
+ }
+}
diff --git a/src/NHibernate/Bytecode/UnwrapProxyPropertyDescriptor.cs b/src/NHibernate/Bytecode/UnwrapProxyPropertyDescriptor.cs
new file mode 100644
index 00000000000..b4012e1778f
--- /dev/null
+++ b/src/NHibernate/Bytecode/UnwrapProxyPropertyDescriptor.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NHibernate.Type;
+
+namespace NHibernate.Bytecode
+{
+ ///
+ /// Descriptor for a property which is mapped as lazy="no-proxy"
+ ///
+ [Serializable]
+ public class UnwrapProxyPropertyDescriptor
+ {
+ public static UnwrapProxyPropertyDescriptor From(
+ Mapping.Property property,
+ int propertyIndex)
+ {
+ return new UnwrapProxyPropertyDescriptor(
+ propertyIndex,
+ property.Name,
+ property.Type
+ );
+ }
+
+ private UnwrapProxyPropertyDescriptor(
+ int propertyIndex,
+ string name,
+ IType type)
+ {
+ PropertyIndex = propertyIndex;
+ Name = name;
+ Type = type;
+ }
+
+ ///
+ /// Access to the index of the property in terms of its position in the entity persister
+ ///
+ public int PropertyIndex { get; }
+
+ ///
+ /// Access to the name of the property
+ ///
+ public string Name { get; }
+
+ ///
+ /// Access to the property's type
+ ///
+ public IType Type { get; }
+ }
+}
diff --git a/src/NHibernate/Engine/Cascade.cs b/src/NHibernate/Engine/Cascade.cs
index 85500f7c9f2..a9ba97a214d 100644
--- a/src/NHibernate/Engine/Cascade.cs
+++ b/src/NHibernate/Engine/Cascade.cs
@@ -113,7 +113,7 @@ public void CascadeOn(IEntityPersister persister, object parent, object anything
IType[] types = persister.PropertyTypes;
CascadeStyle[] cascadeStyles = persister.PropertyCascadeStyles;
- var uninitializedLazyProperties = persister.GetUninitializedLazyProperties(parent);
+ var uninitializedLazyProperties = persister.EntityMetamodel.BytecodeEnhancementMetadata.GetUninitializedLazyProperties(parent);
for (int i = 0; i < types.Length; i++)
{
CascadeStyle style = cascadeStyles[i];
diff --git a/src/NHibernate/Engine/EntityEntry.cs b/src/NHibernate/Engine/EntityEntry.cs
index aceb9894457..1ae1daaa16d 100644
--- a/src/NHibernate/Engine/EntityEntry.cs
+++ b/src/NHibernate/Engine/EntityEntry.cs
@@ -233,7 +233,11 @@ public void PostUpdate(object entity, object[] updatedState, object nextVersion)
version = nextVersion;
Persister.SetPropertyValue(entity, Persister.VersionProperty, nextVersion);
}
- FieldInterceptionHelper.ClearDirty(entity);
+
+ if (Persister.IsInstrumented)
+ {
+ persister.EntityMetamodel.BytecodeEnhancementMetadata.ExtractInterceptor(entity)?.ClearDirty();
+ }
}
///
@@ -264,8 +268,8 @@ public bool RequiresDirtyCheck(object entity)
{
return
IsModifiableEntity()
- && (Persister.HasMutableProperties || !FieldInterceptionHelper.IsInstrumented(entity)
- || FieldInterceptionHelper.ExtractFieldInterceptor(entity).IsDirty);
+ && (Persister.HasMutableProperties || !Persister.IsInstrumented
+ || (Persister.EntityMetamodel.BytecodeEnhancementMetadata.ExtractInterceptor(entity)?.IsDirty ?? true));
}
///
diff --git a/src/NHibernate/Event/Default/AbstractSaveEventListener.cs b/src/NHibernate/Event/Default/AbstractSaveEventListener.cs
index 63e94980222..530aed15d26 100644
--- a/src/NHibernate/Event/Default/AbstractSaveEventListener.cs
+++ b/src/NHibernate/Event/Default/AbstractSaveEventListener.cs
@@ -299,10 +299,11 @@ protected virtual object PerformSaveOrReplicate(object entity, EntityKey key, IE
private void MarkInterceptorDirty(object entity, IEntityPersister persister, IEventSource source)
{
- if (FieldInterceptionHelper.IsInstrumented(entity))
+ if (persister.IsInstrumented)
{
- IFieldInterceptor interceptor = FieldInterceptionHelper.InjectFieldInterceptor(entity, persister.EntityName, persister.MappedClass, null, null, source);
- interceptor.MarkDirty();
+ var interceptor = persister.EntityMetamodel.BytecodeEnhancementMetadata
+ .InjectInterceptor(entity, false, source);
+ interceptor?.MarkDirty();
}
}
diff --git a/src/NHibernate/Event/Default/DefaultMergeEventListener.cs b/src/NHibernate/Event/Default/DefaultMergeEventListener.cs
index b304bd16512..31781db0df4 100644
--- a/src/NHibernate/Event/Default/DefaultMergeEventListener.cs
+++ b/src/NHibernate/Event/Default/DefaultMergeEventListener.cs
@@ -380,7 +380,7 @@ protected virtual void EntityIsDetached(MergeEvent @event, IDictionary copyCache
CopyValues(persister, entity, target, source, copyCache);
//copyValues works by reflection, so explicitly mark the entity instance dirty
- MarkInterceptorDirty(entity, target);
+ MarkInterceptorDirty(entity, persister, target);
@event.Result = result;
}
@@ -400,15 +400,12 @@ protected virtual bool InvokeUpdateLifecycle(object entity, IEntityPersister per
return false;
}
- private void MarkInterceptorDirty(object entity, object target)
+ private void MarkInterceptorDirty(object entity, IEntityPersister persister, object target)
{
- if (FieldInterceptionHelper.IsInstrumented(entity))
+ if (persister.IsInstrumented)
{
- IFieldInterceptor interceptor = FieldInterceptionHelper.ExtractFieldInterceptor(target);
- if (interceptor != null)
- {
- interceptor.MarkDirty();
- }
+ var interceptor = persister.EntityMetamodel.BytecodeEnhancementMetadata.ExtractInterceptor(target);
+ interceptor?.MarkDirty();
}
}
diff --git a/src/NHibernate/Impl/SessionImpl.cs b/src/NHibernate/Impl/SessionImpl.cs
index 3e999ddd9df..fa980fa038a 100644
--- a/src/NHibernate/Impl/SessionImpl.cs
+++ b/src/NHibernate/Impl/SessionImpl.cs
@@ -958,11 +958,11 @@ public override string BestGuessEntityName(object entity)
}
entity = initializer.GetImplementation();
}
- if (FieldInterceptionHelper.IsInstrumented(entity))
+
+ if (entity is IFieldInterceptorAccessor interceptorAccessor && interceptorAccessor.FieldInterceptor != null)
{
// NH: support of field-interceptor-proxy
- IFieldInterceptor interceptor = FieldInterceptionHelper.ExtractFieldInterceptor(entity);
- return interceptor.EntityName;
+ return interceptorAccessor.FieldInterceptor.EntityName;
}
EntityEntry entry = persistenceContext.GetEntry(entity);
if (entry == null)
diff --git a/src/NHibernate/Intercept/FieldInterceptionHelper.cs b/src/NHibernate/Intercept/FieldInterceptionHelper.cs
index a1ad727b9d9..84c07b21077 100644
--- a/src/NHibernate/Intercept/FieldInterceptionHelper.cs
+++ b/src/NHibernate/Intercept/FieldInterceptionHelper.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using NHibernate.Engine;
@@ -21,17 +22,20 @@ public static bool IsInstrumented(System.Type entityClass)
return Cfg.Environment.BytecodeProvider.ProxyFactoryFactory.IsInstrumented(entityClass);
}
+ [Obsolete("This method has no more usages and will be removed in a future version")]
public static bool IsInstrumented(object entity)
{
return entity is IFieldInterceptorAccessor;
}
+ [Obsolete("This method has no more usages and will be removed in a future version")]
public static IFieldInterceptor ExtractFieldInterceptor(object entity)
{
var fieldInterceptorAccessor = entity as IFieldInterceptorAccessor;
return fieldInterceptorAccessor == null ? null : fieldInterceptorAccessor.FieldInterceptor;
}
+ [Obsolete("Use IBytecodeEnhancementMetadata.InjectInterceptor method instead")]
public static IFieldInterceptor InjectFieldInterceptor(object entity, string entityName,
System.Type mappedClass,
ISet uninitializedFieldNames,
@@ -48,6 +52,7 @@ public static IFieldInterceptor InjectFieldInterceptor(object entity, string ent
return null;
}
+ [Obsolete("This method has no more usages and will be removed in a future version")]
public static void ClearDirty(object entity)
{
IFieldInterceptor interceptor = ExtractFieldInterceptor(entity);
@@ -57,6 +62,7 @@ public static void ClearDirty(object entity)
}
}
+ [Obsolete("This method has no more usages and will be removed in a future version")]
public static void MarkDirty(object entity)
{
IFieldInterceptor interceptor = ExtractFieldInterceptor(entity);
@@ -66,4 +72,4 @@ public static void MarkDirty(object entity)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/NHibernate/NHibernateUtil.cs b/src/NHibernate/NHibernateUtil.cs
index 2831f3d6298..fcc7a894e94 100644
--- a/src/NHibernate/NHibernateUtil.cs
+++ b/src/NHibernate/NHibernateUtil.cs
@@ -588,9 +588,9 @@ public static bool IsPropertyInitialized(object proxy, string propertyName)
entity = proxy;
}
- if (FieldInterceptionHelper.IsInstrumented(entity))
+ if (entity is IFieldInterceptorAccessor interceptorAccessor)
{
- IFieldInterceptor interceptor = FieldInterceptionHelper.ExtractFieldInterceptor(entity);
+ var interceptor = interceptorAccessor.FieldInterceptor;
return interceptor == null || interceptor.IsInitializedField(propertyName);
}
else
diff --git a/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs b/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs
index bb5d959f453..85d98154acd 100644
--- a/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs
+++ b/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs
@@ -26,6 +26,7 @@
using Property=NHibernate.Mapping.Property;
using NHibernate.SqlTypes;
using System.Linq;
+using NHibernate.Bytecode;
namespace NHibernate.Persister.Entity
{
@@ -683,6 +684,9 @@ public virtual string VersionColumnName
get { return versionColumnName; }
}
+ // 6.0 TODO: Add into IEntityPersister and simplify .EntityMetamodel.BytecodeEnhancementMetadata external calls
+ public IBytecodeEnhancementMetadata InstrumentationMetadata => EntityMetamodel.BytecodeEnhancementMetadata;
+
[Obsolete("Please use RootTableName instead.")]
protected internal string VersionedTableName
{
@@ -1281,7 +1285,7 @@ public virtual object InitializeLazyProperty(string fieldName, object entity, IS
fieldName);
}
- var uninitializedLazyProperties = GetUninitializedLazyProperties(entity);
+ var uninitializedLazyProperties = InstrumentationMetadata.GetUninitializedLazyProperties(entity);
if (HasCache && session.CacheMode.HasFlag(CacheMode.Get))
{
CacheKey cacheKey = session.GenerateCacheKey(id, IdentifierType, EntityName);
@@ -3220,7 +3224,7 @@ private bool HasDirtyLazyProperties(int[] dirtyFields, object obj)
{
// When having a dirty lazy property and the entity is not yet initialized we have to use a dynamic update for
// it even if it is disabled in order to have it updated.
- return GetUninitializedLazyProperties(obj).Count > 0 && dirtyFields.Any(i => PropertyLaziness[i]);
+ return InstrumentationMetadata.GetUninitializedLazyProperties(obj).Count > 0 && dirtyFields.Any(i => PropertyLaziness[i]);
}
public object Insert(object[] fields, object obj, ISessionImplementor session)
@@ -3928,17 +3932,17 @@ public virtual bool HasLazyProperties
public virtual void AfterReassociate(object entity, ISessionImplementor session)
{
- if (FieldInterceptionHelper.IsInstrumented(entity))
+ if (IsInstrumented)
{
- IFieldInterceptor interceptor = FieldInterceptionHelper.ExtractFieldInterceptor(entity);
+ var interceptor = InstrumentationMetadata.ExtractInterceptor(entity);
if (interceptor != null)
{
interceptor.Session = session;
}
else
{
- IFieldInterceptor fieldInterceptor = FieldInterceptionHelper.InjectFieldInterceptor(entity, EntityName, MappedClass, null, null, session);
- fieldInterceptor.MarkDirty();
+ var fieldInterceptor = InstrumentationMetadata.InjectInterceptor(entity, false, session);
+ fieldInterceptor?.MarkDirty();
}
}
}
@@ -4089,7 +4093,7 @@ public string SelectFragment(
public bool IsInstrumented
{
- get { return EntityTuplizer.IsInstrumented; }
+ get { return InstrumentationMetadata.EnhancedForLazyLoading; }
}
public bool HasInsertGeneratedProperties
@@ -4107,30 +4111,6 @@ public void AfterInitialize(object entity, bool lazyPropertiesAreUnfetched, ISes
EntityTuplizer.AfterInitialize(entity, lazyPropertiesAreUnfetched, session);
}
- internal ISet GetUninitializedLazyProperties(object entity)
- {
- return EntityTuplizer.GetUninitializedLazyProperties(entity) ?? new HashSet(lazyPropertyNames);
- }
-
- internal ISet GetUninitializedLazyProperties(object[] state)
- {
- if (!HasLazyProperties)
- {
- return CollectionHelper.EmptySet();
- }
-
- var uninitializedProperties = new HashSet();
- for (var j = 0; j < lazyPropertyNames.Length; j++)
- {
- if (state[lazyPropertyNumbers[j]] == LazyPropertyInitializer.UnfetchedProperty)
- {
- uninitializedProperties.Add(lazyPropertyNames[j]);
- }
- }
-
- return uninitializedProperties;
- }
-
public virtual bool[] PropertyUpdateability
{
get { return entityMetamodel.PropertyUpdateability; }
diff --git a/src/NHibernate/Persister/Entity/IEntityPersister.cs b/src/NHibernate/Persister/Entity/IEntityPersister.cs
index b757d8a7cf8..7ba82488bb9 100644
--- a/src/NHibernate/Persister/Entity/IEntityPersister.cs
+++ b/src/NHibernate/Persister/Entity/IEntityPersister.cs
@@ -623,59 +623,5 @@ public static int GetBatchSize(this IEntityPersister persister)
return 1;
}
-
- //6.0 TODO: Merge into IEntityPersister
- internal static ISet GetUninitializedLazyProperties(this IEntityPersister persister, object entity)
- {
- if (persister is AbstractEntityPersister abstractEntityPersister)
- {
- return abstractEntityPersister.GetUninitializedLazyProperties(entity);
- }
-
- if (!persister.HasUninitializedLazyProperties(entity))
- {
- return CollectionHelper.EmptySet();
- }
-
- // Assume they are all uninitialized.
- var result = new HashSet();
- for (var i = 0; i < persister.PropertyLaziness.Length; i++)
- {
- if (persister.PropertyLaziness[i])
- {
- result.Add(persister.PropertyNames[i]);
- }
- }
-
- return result;
- }
-
- ///
- /// Get uninitialized lazy properties from entity state
- ///
- //6.0 TODO: Merge into IEntityPersister
- public static ISet GetUninitializedLazyProperties(this IEntityPersister persister, object[] state)
- {
- if (persister is AbstractEntityPersister abstractEntityPersister)
- {
- return abstractEntityPersister.GetUninitializedLazyProperties(state);
- }
-
- if (!persister.HasLazyProperties)
- {
- return CollectionHelper.EmptySet();
- }
-
- var result = new HashSet();
- for (var i = 0; i < persister.PropertyLaziness.Length; i++)
- {
- if (persister.PropertyLaziness[i] && state[i] == LazyPropertyInitializer.UnfetchedProperty)
- {
- result.Add(persister.PropertyNames[i]);
- }
- }
-
- return result;
- }
}
}
diff --git a/src/NHibernate/Tuple/Entity/BytecodeEnhancementMetadataNonPocoImpl.cs b/src/NHibernate/Tuple/Entity/BytecodeEnhancementMetadataNonPocoImpl.cs
new file mode 100644
index 00000000000..cd4dc440fa3
--- /dev/null
+++ b/src/NHibernate/Tuple/Entity/BytecodeEnhancementMetadataNonPocoImpl.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NHibernate.Bytecode;
+using NHibernate.Engine;
+using NHibernate.Intercept;
+using NHibernate.Util;
+
+namespace NHibernate.Tuple.Entity
+{
+ ///
+ /// Author: Steve Ebersole
+ ///
+ [Serializable]
+ public class BytecodeEnhancementMetadataNonPocoImpl : IBytecodeEnhancementMetadata
+ {
+ private readonly string _errorMessage;
+
+ public BytecodeEnhancementMetadataNonPocoImpl(string entityName)
+ {
+ EntityName = entityName;
+ LazyPropertiesMetadata = LazyPropertiesMetadata.NonEnhanced(entityName);
+ UnwrapProxyPropertiesMetadata = UnwrapProxyPropertiesMetadata.NonEnhanced(entityName);
+ _errorMessage = $"Entity [{entityName}] is non-poco, and therefore not instrumented";
+ }
+
+ ///
+ public string EntityName { get; }
+
+ ///
+ public bool EnhancedForLazyLoading => false;
+
+ ///
+ public LazyPropertiesMetadata LazyPropertiesMetadata { get; }
+
+ ///
+ public UnwrapProxyPropertiesMetadata UnwrapProxyPropertiesMetadata { get; }
+
+ ///
+ public IFieldInterceptor InjectInterceptor(object entity, bool lazyPropertiesAreUnfetched, ISessionImplementor session)
+ {
+ throw new NotInstrumentedException(_errorMessage);
+ }
+
+ ///
+ public IFieldInterceptor ExtractInterceptor(object entity)
+ {
+ throw new NotInstrumentedException(_errorMessage);
+ }
+
+ ///
+ public ISet GetUninitializedLazyProperties(object entity)
+ {
+ return CollectionHelper.EmptySet();
+ }
+
+ ///
+ public ISet GetUninitializedLazyProperties(object[] entityState)
+ {
+ return CollectionHelper.EmptySet();
+ }
+ }
+}
diff --git a/src/NHibernate/Tuple/Entity/BytecodeEnhancementMetadataPocoImpl.cs b/src/NHibernate/Tuple/Entity/BytecodeEnhancementMetadataPocoImpl.cs
new file mode 100644
index 00000000000..2f1ef4007d3
--- /dev/null
+++ b/src/NHibernate/Tuple/Entity/BytecodeEnhancementMetadataPocoImpl.cs
@@ -0,0 +1,214 @@
+using System;
+using System.Collections.Generic;
+using NHibernate.Bytecode;
+using NHibernate.Engine;
+using NHibernate.Intercept;
+using NHibernate.Mapping;
+using NHibernate.Util;
+
+namespace NHibernate.Tuple.Entity
+{
+ ///
+ /// Author: Steve Ebersole
+ ///
+ [Serializable]
+ public class BytecodeEnhancementMetadataPocoImpl : IBytecodeEnhancementMetadata
+ {
+ private readonly System.Type _entityType;
+
+ public static IBytecodeEnhancementMetadata From(
+ PersistentClass persistentClass,
+ ICollection lazyPropertyDescriptors,
+ ICollection unwrapProxyPropertyDescriptors)
+ {
+ var mappedClass = persistentClass.MappedClass;
+ var enhancedForLazyLoading = lazyPropertyDescriptors?.Count > 0 || unwrapProxyPropertyDescriptors?.Count > 0;
+
+ // We have to check all subclasses if any of them is enhanced for lazy loading as the
+ // root class will be enhanced when any of the subclasses is enhanced, even if it
+ // does not have any lazy properties.
+ // If we do not check the subclasses, where the root-entity has no lazy properties
+ // we will eager-load/double-load those properties (NH2488).
+ if (!enhancedForLazyLoading)
+ {
+ foreach (var persistentSubclass in persistentClass.SubclassClosureIterator)
+ {
+ enhancedForLazyLoading |= IsEnhancedForLazyLoading(persistentSubclass);
+ if (enhancedForLazyLoading)
+ {
+ break;
+ }
+ }
+ }
+
+ var lazyPropertiesMetadata = enhancedForLazyLoading
+ ? LazyPropertiesMetadata.From(persistentClass.EntityName, lazyPropertyDescriptors)
+ : LazyPropertiesMetadata.NonEnhanced(persistentClass.EntityName);
+
+ var unwrapProxyPropertiesMetadata = enhancedForLazyLoading
+ ? UnwrapProxyPropertiesMetadata.From(persistentClass.EntityName, unwrapProxyPropertyDescriptors)
+ : UnwrapProxyPropertiesMetadata.NonEnhanced(persistentClass.EntityName);
+
+ return new BytecodeEnhancementMetadataPocoImpl(
+ persistentClass.EntityName,
+ mappedClass,
+ enhancedForLazyLoading,
+ lazyPropertiesMetadata,
+ unwrapProxyPropertiesMetadata
+ );
+ }
+
+ ///
+ /// Check for a if is enhanced for lazy loading.
+ /// NOTE: The logic was taken from .
+ ///
+ /// The persistent class to check.
+ /// Whether the persistent class is enhanced for lazy loading or not.
+ private static bool IsEnhancedForLazyLoading(PersistentClass persistentClass)
+ {
+ var lazyAvailable = persistentClass.HasPocoRepresentation
+ && FieldInterceptionHelper.IsInstrumented(persistentClass.MappedClass);
+
+ var lazy = persistentClass.IsLazy && (!persistentClass.HasPocoRepresentation ||
+ !ReflectHelper.IsFinalClass(persistentClass.ProxyInterface));
+ lazyAvailable &= lazy;
+ if (!lazyAvailable)
+ {
+ return false;
+ }
+
+ foreach (var prop in persistentClass.PropertyIterator)
+ {
+ // NH: A lazy property is a simple property marked with lazy=true
+ var islazyProperty = prop.IsLazy && (!prop.IsEntityRelation || prop.UnwrapProxy);
+ // NH: A Relation (in this case many-to-one or one-to-one) marked as "no-proxy"
+ var isUnwrapProxy = prop.UnwrapProxy;
+
+ if (islazyProperty || isUnwrapProxy)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public BytecodeEnhancementMetadataPocoImpl(
+ string entityName,
+ System.Type entityType,
+ bool enhancedForLazyLoading,
+ LazyPropertiesMetadata lazyPropertiesMetadata,
+ UnwrapProxyPropertiesMetadata unwrapProxyPropertiesMetadata)
+ {
+ EntityName = entityName;
+ _entityType = entityType;
+ EnhancedForLazyLoading = enhancedForLazyLoading;
+ LazyPropertiesMetadata = lazyPropertiesMetadata;
+ UnwrapProxyPropertiesMetadata = unwrapProxyPropertiesMetadata;
+ }
+
+ ///
+ public string EntityName { get; }
+
+ ///
+ public bool EnhancedForLazyLoading { get; }
+
+ ///
+ public LazyPropertiesMetadata LazyPropertiesMetadata { get; }
+
+ ///
+ public UnwrapProxyPropertiesMetadata UnwrapProxyPropertiesMetadata { get; }
+
+ ///
+ public IFieldInterceptor InjectInterceptor(object entity, bool lazyPropertiesAreUnfetched, ISessionImplementor session)
+ {
+ if (!EnhancedForLazyLoading)
+ {
+ throw new NotInstrumentedException($"Entity class [{_entityType}] is not enhanced for lazy loading");
+ }
+
+ if (!(entity is IFieldInterceptorAccessor fieldInterceptorAccessor))
+ {
+ return null; // Can happen when a saved entity is refreshed within the same session NH2860
+ }
+
+ if (entity.GetType().BaseType != _entityType)
+ {
+ throw new ArgumentException(
+ $"Passed entity instance [{entity}] is not of expected type [{EntityName}]");
+ }
+
+ var fieldInterceptorImpl = new DefaultFieldInterceptor(
+ session,
+ LazyPropertiesMetadata.HasLazyProperties && lazyPropertiesAreUnfetched
+ ? new HashSet(LazyPropertiesMetadata.LazyPropertyNames)
+ : null,
+ UnwrapProxyPropertiesMetadata.UnwrapProxyPropertyNames,
+ EntityName,
+ _entityType);
+ fieldInterceptorAccessor.FieldInterceptor = fieldInterceptorImpl;
+
+ return fieldInterceptorImpl;
+ }
+
+ ///
+ public IFieldInterceptor ExtractInterceptor(object entity)
+ {
+ if (!EnhancedForLazyLoading)
+ {
+ throw new NotInstrumentedException($"Entity class [{_entityType}] is not enhanced for lazy loading");
+ }
+
+ if (!(entity is IFieldInterceptorAccessor fieldInterceptorAccessor))
+ {
+ return null;
+ }
+
+ var interceptor = fieldInterceptorAccessor.FieldInterceptor;
+ if (interceptor == null)
+ {
+ return null;
+ }
+
+ if (_entityType != interceptor.MappedClass)
+ {
+ throw new ArgumentException(
+ $"Passed entity instance [{entity}] is not of expected type [{EntityName}]");
+ }
+
+ return fieldInterceptorAccessor.FieldInterceptor;
+ }
+
+ ///
+ public ISet GetUninitializedLazyProperties(object entity)
+ {
+ var interceptor = LazyPropertiesMetadata.HasLazyProperties ? ExtractInterceptor(entity) : null;
+ if (interceptor == null)
+ {
+ return CollectionHelper.EmptySet();
+ }
+
+ return interceptor.GetUninitializedFields() ?? LazyPropertiesMetadata.LazyPropertyNames;
+ }
+
+ ///
+ public ISet GetUninitializedLazyProperties(object[] entityState)
+ {
+ if (!LazyPropertiesMetadata.HasLazyProperties)
+ {
+ return CollectionHelper.EmptySet();
+ }
+
+ var uninitializedProperties = new HashSet();
+ foreach (var propertyDescriptor in LazyPropertiesMetadata.LazyPropertyDescriptors)
+ {
+ if (entityState[propertyDescriptor.PropertyIndex] == LazyPropertyInitializer.UnfetchedProperty)
+ {
+ uninitializedProperties.Add(propertyDescriptor.Name);
+ }
+ }
+
+ return uninitializedProperties;
+ }
+ }
+}
diff --git a/src/NHibernate/Tuple/Entity/EntityMetamodel.cs b/src/NHibernate/Tuple/Entity/EntityMetamodel.cs
index 9f81571059b..7fb104dac86 100644
--- a/src/NHibernate/Tuple/Entity/EntityMetamodel.cs
+++ b/src/NHibernate/Tuple/Entity/EntityMetamodel.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
-
+using NHibernate.Bytecode;
using NHibernate.Engine;
using NHibernate.Intercept;
using NHibernate.Mapping;
@@ -103,6 +103,8 @@ public EntityMetamodel(PersistentClass persistentClass, ISessionFactoryImplement
propertySpan = persistentClass.PropertyClosureSpan;
properties = new StandardProperty[propertySpan];
List naturalIdNumbers = new List();
+ var lazyPropertyDescriptors = new List();
+ var unwrapProxyPropertyDescriptors = new List();
propertyNames = new string[propertySpan];
propertyTypes = new IType[propertySpan];
@@ -182,10 +184,12 @@ public EntityMetamodel(PersistentClass persistentClass, ISessionFactoryImplement
if (islazyProperty)
{
hasLazy = true;
+ lazyPropertyDescriptors.Add(LazyPropertyDescriptor.From(prop, i, lazyPropertyDescriptors.Count));
}
if (isUnwrapProxy)
{
hasUnwrapProxyForProperties = true;
+ unwrapProxyPropertyDescriptors.Add(UnwrapProxyPropertyDescriptor.From(prop, i));
}
propertyLaziness[i] = islazyProperty;
@@ -316,6 +320,16 @@ public EntityMetamodel(PersistentClass persistentClass, ISessionFactoryImplement
EntityMode = persistentClass.HasPocoRepresentation ? EntityMode.Poco : EntityMode.Map;
+ if (persistentClass.HasPocoRepresentation)
+ {
+ BytecodeEnhancementMetadata = BytecodeEnhancementMetadataPocoImpl
+ .From(persistentClass, lazyPropertyDescriptors, unwrapProxyPropertyDescriptors);
+ }
+ else
+ {
+ BytecodeEnhancementMetadata = new BytecodeEnhancementMetadataNonPocoImpl(persistentClass.EntityName);
+ }
+
var entityTuplizerFactory = new EntityTuplizerFactory();
var tuplizerClassName = persistentClass.GetTuplizerImplClassName(EntityMode);
Tuplizer = tuplizerClassName == null
@@ -716,5 +730,7 @@ public int[] NaturalIdentifierProperties
{
get { return naturalIdPropertyNumbers; }
}
+
+ public IBytecodeEnhancementMetadata BytecodeEnhancementMetadata { get; }
}
}
diff --git a/src/NHibernate/Tuple/Entity/IEntityTuplizer.cs b/src/NHibernate/Tuple/Entity/IEntityTuplizer.cs
index 6f697e2c04d..397bdd595d6 100644
--- a/src/NHibernate/Tuple/Entity/IEntityTuplizer.cs
+++ b/src/NHibernate/Tuple/Entity/IEntityTuplizer.cs
@@ -119,23 +119,4 @@ public interface IEntityTuplizer : ITuplizer
/// True if uninitialized lazy properties were found; false otherwise.
bool HasUninitializedLazyProperties(object entity);
}
-
- internal static class EntityTuplizerExtensions
- {
- //6.0 TODO: Merge into IEntityTuplizer
- internal static ISet GetUninitializedLazyProperties(this IEntityTuplizer entityTuplizer, object entity)
- {
- if (entityTuplizer is AbstractEntityTuplizer abstractEntityTuplizer)
- {
- return abstractEntityTuplizer.GetUninitializedLazyProperties(entity);
- }
-
- if (!entityTuplizer.HasUninitializedLazyProperties(entity))
- {
- return CollectionHelper.EmptySet();
- }
-
- return null; // The caller should use all lazy properties as the result
- }
- }
}
diff --git a/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs b/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs
index 2deb5f607ab..5dd46ce470a 100644
--- a/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs
+++ b/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs
@@ -24,8 +24,6 @@ public class PocoEntityTuplizer : AbstractEntityTuplizer
private readonly System.Type proxyInterface;
private readonly bool islifecycleImplementor;
private readonly bool isValidatableImplementor;
- private readonly HashSet lazyPropertyNames = new HashSet();
- private readonly HashSet unwrapProxyPropertyNames = new HashSet();
[NonSerialized]
private IReflectionOptimizer optimizer;
private readonly IProxyValidator proxyValidator;
@@ -59,13 +57,6 @@ public PocoEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappe
islifecycleImplementor = typeof(ILifecycle).IsAssignableFrom(mappedClass);
isValidatableImplementor = typeof(IValidatable).IsAssignableFrom(mappedClass);
- foreach (Mapping.Property property in mappedEntity.PropertyClosureIterator)
- {
- if (property.IsLazy)
- lazyPropertyNames.Add(property.Name);
- if (property.UnwrapProxy)
- unwrapProxyPropertyNames.Add(property.Name);
- }
SetReflectionOptimizer();
Instantiator = BuildInstantiator(mappedEntity);
@@ -80,16 +71,7 @@ public override System.Type ConcreteProxyClass
get { return proxyInterface; }
}
- public override bool IsInstrumented
- {
- get
- {
- // NH: we can't really check for EntityMetamodel.HasLazyProperties and/or EntityMetamodel.HasUnwrapProxyForProperties here
- // because this property is used even where subclasses has lazy-properties.
- // Checking it here, where the root-entity has no lazy properties we will eager-load/double-load those properties.
- return FieldInterceptionHelper.IsInstrumented(MappedClass);
- }
- }
+ public override bool IsInstrumented => EntityMetamodel.BytecodeEnhancementMetadata.EnhancedForLazyLoading;
public override System.Type MappedClass
{
@@ -111,12 +93,12 @@ protected override IInstantiator BuildInstantiator(PersistentClass persistentCla
if (optimizer == null)
{
log.Debug("Create Instantiator without optimizer for:{0}", persistentClass.MappedClass.FullName);
- return new PocoInstantiator(persistentClass, null, ProxyFactory, EntityMetamodel.HasLazyProperties || EntityMetamodel.HasUnwrapProxyForProperties);
+ return new PocoInstantiator(persistentClass, null, ProxyFactory, IsInstrumented);
}
else
{
log.Debug("Create Instantiator using optimizer for:{0}", persistentClass.MappedClass.FullName);
- return new PocoInstantiator(persistentClass, optimizer.InstantiationOptimizer, ProxyFactory, EntityMetamodel.HasLazyProperties || EntityMetamodel.HasUnwrapProxyForProperties);
+ return new PocoInstantiator(persistentClass, optimizer.InstantiationOptimizer, ProxyFactory, IsInstrumented);
}
}
@@ -229,10 +211,9 @@ protected virtual IProxyFactory BuildProxyFactoryInternal(PersistentClass @class
public override void AfterInitialize(object entity, bool lazyPropertiesAreUnfetched, ISessionImplementor session)
{
- if (IsInstrumented && (EntityMetamodel.HasLazyProperties || EntityMetamodel.HasUnwrapProxyForProperties))
+ if (IsInstrumented)
{
- HashSet lazyProps = lazyPropertiesAreUnfetched && EntityMetamodel.HasLazyProperties ? new HashSet(lazyPropertyNames) : null;
- FieldInterceptionHelper.InjectFieldInterceptor(entity, EntityName, this.MappedClass ,lazyProps, unwrapProxyPropertyNames, session);
+ EntityMetamodel.BytecodeEnhancementMetadata.InjectInterceptor(entity, lazyPropertiesAreUnfetched, session);
}
}
@@ -269,7 +250,7 @@ public override bool HasUninitializedLazyProperties(object entity)
{
if (EntityMetamodel.HasLazyProperties)
{
- IFieldInterceptor callback = FieldInterceptionHelper.ExtractFieldInterceptor(entity);
+ var callback = EntityMetamodel.BytecodeEnhancementMetadata.ExtractInterceptor(entity);
return callback != null && !callback.IsInitialized;
}
else
@@ -285,13 +266,7 @@ internal override ISet GetUninitializedLazyProperties(object entity)
return CollectionHelper.EmptySet();
}
- var interceptor = FieldInterceptionHelper.ExtractFieldInterceptor(entity);
- if (interceptor == null)
- {
- return CollectionHelper.EmptySet();
- }
-
- return interceptor.GetUninitializedFields() ?? lazyPropertyNames;
+ return EntityMetamodel.BytecodeEnhancementMetadata.GetUninitializedLazyProperties(entity);
}
public override bool IsLifecycleImplementor