diff --git a/src/EFCore/ChangeTracking/Internal/NavigationFixer.cs b/src/EFCore/ChangeTracking/Internal/NavigationFixer.cs index 15ffc957b0d..d2bb49a27f7 100644 --- a/src/EFCore/ChangeTracking/Internal/NavigationFixer.cs +++ b/src/EFCore/ChangeTracking/Internal/NavigationFixer.cs @@ -14,7 +14,13 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal; /// public class NavigationFixer : INavigationFixer { - private IList? _danglingJoinEntities; + private IList<( + InternalEntityEntry Entry, + InternalEntityEntry OtherEntry, + ISkipNavigation SkipNavigation, + bool FromQuery, + bool SetModified)>? _danglingJoinEntities; + private readonly IEntityGraphAttacher _attacher; private bool _inFixup; private bool _inAttachGraph; @@ -43,7 +49,11 @@ public virtual bool BeginDelayedFixup() return false; } - _danglingJoinEntities?.Clear(); + if (_danglingJoinEntities != null) + { + throw new InvalidOperationException(CoreStrings.InvalidDbContext); + } + _inAttachGraph = true; return true; @@ -61,10 +71,10 @@ public virtual void CompleteDelayedFixup() if (_danglingJoinEntities != null) { var dangles = _danglingJoinEntities.ToList(); - _danglingJoinEntities.Clear(); - foreach (var synthesize in dangles) + _danglingJoinEntities = null; + foreach (var arguments in dangles) { - synthesize(); + FindOrCreateJoinEntry(arguments); } } } @@ -1009,9 +1019,15 @@ private void FindOrCreateJoinEntry( } else { - _danglingJoinEntities ??= new List(); - - _danglingJoinEntities.Add(() => FindOrCreateJoinEntry(arguments)); + _danglingJoinEntities ??= + new List<( + InternalEntityEntry Entry, + InternalEntityEntry OtherEntry, + ISkipNavigation SkipNavigation, + bool FromQuery, + bool SetModified)>(); + + _danglingJoinEntities.Add(arguments); } } diff --git a/src/EFCore/Properties/CoreStrings.Designer.cs b/src/EFCore/Properties/CoreStrings.Designer.cs index 00ca3230641..62a210f1adf 100644 --- a/src/EFCore/Properties/CoreStrings.Designer.cs +++ b/src/EFCore/Properties/CoreStrings.Designer.cs @@ -1149,6 +1149,12 @@ public static string InvalidAlternateKeyValue(object? entityType, object? keyPro GetString("InvalidAlternateKeyValue", nameof(entityType), nameof(keyProperty)), entityType, keyProperty); + /// + /// A previous error has left the DbContext in an invalid state. Applications should not continue to use a DbContext instance after an InvalidOperationException has been thrown. + /// + public static string InvalidDbContext + => GetString("InvalidDbContext"); + /// /// The specified type '{type}' must be a non-interface reference type to be used as an entity type. /// diff --git a/src/EFCore/Properties/CoreStrings.resx b/src/EFCore/Properties/CoreStrings.resx index 65aa0af24c0..1383d8b33d7 100644 --- a/src/EFCore/Properties/CoreStrings.resx +++ b/src/EFCore/Properties/CoreStrings.resx @@ -547,6 +547,9 @@ Unable to track an entity of type '{entityType}' because alternate key property '{keyProperty}' is null. If the alternate key is not used in a relationship, then consider using a unique index instead. Unique indexes may contain nulls, while alternate keys may not. + + A previous error has left the DbContext in an invalid state. Applications should not continue to use a DbContext instance after an InvalidOperationException has been thrown. + The specified type '{type}' must be a non-interface reference type to be used as an entity type.