Skip to content

Commit

Permalink
Stop keeping a reference to the model in LazyLoader instances and the…
Browse files Browse the repository at this point in the history
… Castle interceptor (#32388)
  • Loading branch information
ajcvickers authored Nov 23, 2023
1 parent 1b59013 commit 84505e3
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 13 deletions.
13 changes: 7 additions & 6 deletions src/EFCore.Proxies/Proxies/Internal/LazyLoadingInterceptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ private static readonly PropertyInfo LazyLoaderProperty
private static readonly MethodInfo LazyLoaderGetter = LazyLoaderProperty.GetMethod!;
private static readonly MethodInfo LazyLoaderSetter = LazyLoaderProperty.SetMethod!;

private readonly IEntityType _entityType;
private ILazyLoader? _loader;
private readonly Dictionary<string, bool> _navigations;

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand All @@ -33,8 +33,11 @@ public LazyLoadingInterceptor(
IEntityType entityType,
ILazyLoader loader)
{
_entityType = entityType;
_loader = loader;
_navigations = entityType!.GetNavigations()
.Cast<INavigationBase>()
.Concat(entityType.GetSkipNavigations())
.ToDictionary(n => n.Name, n => n is INavigation { ForeignKey.IsOwnership: true });
}

/// <summary>
Expand All @@ -61,10 +64,8 @@ public virtual void Intercept(IInvocation invocation)
&& methodName.StartsWith("get_", StringComparison.Ordinal))
{
var navigationName = methodName[4..];
var navigationBase = _entityType.FindNavigation(navigationName)
?? (INavigationBase?)_entityType.FindSkipNavigation(navigationName);

if (navigationBase is not (null or INavigation { ForeignKey.IsOwnership: true }))
if (_navigations.TryGetValue(navigationName, out var isOwnership)
&& !isOwnership)
{
_loader.Load(invocation.Proxy, navigationName);
}
Expand Down
19 changes: 12 additions & 7 deletions src/EFCore/Infrastructure/Internal/LazyLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class LazyLoader : ILazyLoader, IInjectableService
private bool _detached;
private IDictionary<string, bool>? _loadedStates;
private List<(object Entity, string NavigationName)>? _isLoading;
private IEntityType? _entityType;
private Dictionary<string, bool>? _navigations;

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand All @@ -45,7 +45,7 @@ public LazyLoader(
public virtual void Injected(DbContext context, object entity, ParameterBindingInfo bindingInfo)
{
_queryTrackingBehavior = bindingInfo.QueryTrackingBehavior;
_entityType = bindingInfo.StructuralType as IEntityType ?? throw new NotImplementedException();
_navigations ??= InitNavigationsMetadata(bindingInfo.StructuralType as IEntityType ?? throw new NotImplementedException());
}

/// <summary>
Expand Down Expand Up @@ -214,10 +214,9 @@ private bool ShouldLoad(object entity, string navigationName, [NotNullWhen(true)
{
if (!_detached && !IsLoaded(entity, navigationName))
{
var navigation = _entityType?.FindNavigation(navigationName)
?? (INavigationBase?)_entityType?.FindSkipNavigation(navigationName);

if (navigation?.LazyLoadingEnabled != false)
if (_navigations == null
|| !_navigations.TryGetValue(navigationName, out var lazyLoadingEnabled)
|| lazyLoadingEnabled)
{
if (_disposed)
{
Expand Down Expand Up @@ -275,7 +274,13 @@ public virtual void Attaching(DbContext context, IEntityType entityType, object
{
_disposed = false;
_detached = false;
_entityType = entityType;
Context = context;
_navigations ??= InitNavigationsMetadata(entityType);
}

private Dictionary<string, bool> InitNavigationsMetadata(IEntityType entityType)
=> entityType!.GetNavigations()
.Cast<INavigationBase>()
.Concat(entityType.GetSkipNavigations())
.ToDictionary(n => n.Name, n => n.LazyLoadingEnabled);
}

0 comments on commit 84505e3

Please sign in to comment.