diff --git a/src/EFCore/ChangeTracking/ChangeTracker.cs b/src/EFCore/ChangeTracking/ChangeTracker.cs index da8aa7835b4..25d68233002 100644 --- a/src/EFCore/ChangeTracking/ChangeTracker.cs +++ b/src/EFCore/ChangeTracking/ChangeTracker.cs @@ -220,7 +220,7 @@ public virtual bool HasChanges() /// public virtual void DetectChanges() { - if ((string)_model[CoreAnnotationNames.SkipDetectChangesAnnotation] != "true") + if (!((Model)_model).SkipDetectChanges) { ChangeDetector.DetectChanges(StateManager); } diff --git a/src/EFCore/ChangeTracking/CollectionEntry.cs b/src/EFCore/ChangeTracking/CollectionEntry.cs index c27e6332479..96af0410be0 100644 --- a/src/EFCore/ChangeTracking/CollectionEntry.cs +++ b/src/EFCore/ChangeTracking/CollectionEntry.cs @@ -63,7 +63,7 @@ private void LocalDetectChanges() var context = InternalEntry.StateManager.Context; var changeDetector = context.ChangeTracker.AutoDetectChangesEnabled - && (string)context.Model[CoreAnnotationNames.SkipDetectChangesAnnotation] != "true" + && !((Model)context.Model).SkipDetectChanges ? context.GetDependencies().ChangeDetector : null; diff --git a/src/EFCore/ChangeTracking/EntityEntry.cs b/src/EFCore/ChangeTracking/EntityEntry.cs index 5e932a4cebf..16d917f2ce7 100644 --- a/src/EFCore/ChangeTracking/EntityEntry.cs +++ b/src/EFCore/ChangeTracking/EntityEntry.cs @@ -102,7 +102,7 @@ public virtual EntityState State /// public virtual void DetectChanges() { - if ((string)Context.Model[CoreAnnotationNames.SkipDetectChangesAnnotation] != "true") + if (!((Model)Context.Model).SkipDetectChanges) { Context.GetDependencies().ChangeDetector.DetectChanges(InternalEntry); } diff --git a/src/EFCore/ChangeTracking/Internal/StateManager.cs b/src/EFCore/ChangeTracking/Internal/StateManager.cs index c6f90dfafd1..64118aa2399 100644 --- a/src/EFCore/ChangeTracking/Internal/StateManager.cs +++ b/src/EFCore/ChangeTracking/Internal/StateManager.cs @@ -993,7 +993,7 @@ public virtual void CascadeDelete(InternalEntityEntry entry, bool force, IEnumer if (!_changeDetectorInitialized) { _changeDetector = Context.ChangeTracker.AutoDetectChangesEnabled - && (string)Context.Model[CoreAnnotationNames.SkipDetectChangesAnnotation] != "true" + && !((Model)Context.Model).SkipDetectChanges ? Context.GetDependencies().ChangeDetector : null; _changeDetectorInitialized = true; diff --git a/src/EFCore/ChangeTracking/ReferenceEntry.cs b/src/EFCore/ChangeTracking/ReferenceEntry.cs index 93cc1cb5010..eddcbcb4f4f 100644 --- a/src/EFCore/ChangeTracking/ReferenceEntry.cs +++ b/src/EFCore/ChangeTracking/ReferenceEntry.cs @@ -70,7 +70,7 @@ private void LocalDetectChanges() { var context = InternalEntry.StateManager.Context; if (context.ChangeTracker.AutoDetectChangesEnabled - && (string)context.Model[CoreAnnotationNames.SkipDetectChangesAnnotation] != "true") + && !((Model)context.Model).SkipDetectChanges) { context.GetDependencies().ChangeDetector.DetectChanges(target); } diff --git a/src/EFCore/Metadata/Conventions/ChangeTrackingStrategyConvention.cs b/src/EFCore/Metadata/Conventions/ChangeTrackingStrategyConvention.cs index 0a4ae96eefe..731d551f4af 100644 --- a/src/EFCore/Metadata/Conventions/ChangeTrackingStrategyConvention.cs +++ b/src/EFCore/Metadata/Conventions/ChangeTrackingStrategyConvention.cs @@ -41,7 +41,10 @@ public virtual void ProcessModelFinalizing( } } - modelBuilder.HasAnnotation(CoreAnnotationNames.SkipDetectChangesAnnotation, "true"); + if (modelBuilder.Metadata is Model model) + { + model.SetSkipDetectChanges(true); + } } } } diff --git a/src/EFCore/Metadata/Internal/CoreAnnotationNames.cs b/src/EFCore/Metadata/Internal/CoreAnnotationNames.cs index e170f185413..7dc0c460b3f 100644 --- a/src/EFCore/Metadata/Internal/CoreAnnotationNames.cs +++ b/src/EFCore/Metadata/Internal/CoreAnnotationNames.cs @@ -257,14 +257,6 @@ public static class CoreAnnotationNames /// public const string AmbiguousField = "BackingFieldConvention:AmbiguousField"; - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string SkipDetectChangesAnnotation = "ChangeDetector.SkipDetectChanges"; - /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in @@ -315,7 +307,6 @@ public static class CoreAnnotationNames AmbiguousNavigations, DuplicateServiceProperties, AmbiguousField, - SkipDetectChangesAnnotation, SkipChangeTrackingStrategyValidationAnnotation }; } diff --git a/src/EFCore/Metadata/Internal/Model.cs b/src/EFCore/Metadata/Internal/Model.cs index c19e5eb98e4..e5274c68234 100644 --- a/src/EFCore/Metadata/Internal/Model.cs +++ b/src/EFCore/Metadata/Internal/Model.cs @@ -61,6 +61,8 @@ private readonly Dictionary _ignoredTypeNames private readonly Dictionary _sharedTypes = new Dictionary { { DefaultPropertyBagType, ConfigurationSource.Convention } }; + private bool? _skipDetectChanges; + /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in @@ -989,6 +991,31 @@ private IModel MakeReadonly() public virtual PropertyInfo FindIndexerPropertyInfo([NotNull] Type type) => _indexerPropertyInfoMap.GetOrAdd(type, type.FindIndexerProperty()); + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + public virtual bool SkipDetectChanges + { + get => _skipDetectChanges ?? false; + set => SetSkipDetectChanges(value); + } + + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + public virtual bool? SetSkipDetectChanges(bool? skipDetectChanges) + { + _skipDetectChanges = skipDetectChanges; + + return skipDetectChanges; + } + /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in diff --git a/src/EFCore/Update/Internal/UpdateAdapter.cs b/src/EFCore/Update/Internal/UpdateAdapter.cs index d84674ff158..963e5c90907 100644 --- a/src/EFCore/Update/Internal/UpdateAdapter.cs +++ b/src/EFCore/Update/Internal/UpdateAdapter.cs @@ -115,7 +115,7 @@ public virtual IEnumerable Entries /// public virtual void DetectChanges() { - if ((string)_stateManager.Model[CoreAnnotationNames.SkipDetectChangesAnnotation] != "true") + if (!((Model)_stateManager.Model).SkipDetectChanges) { _changeDetector.DetectChanges(_stateManager); }