From 465f7ba4686ad7022d84e2eba872288ef3423d50 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Mon, 14 Sep 2020 12:05:11 -0700 Subject: [PATCH] Change ChangeTrackingStrategy from annotation to field Fixes #22503 --- .../ConventionEntityTypeExtensions.cs | 7 +++-- .../Extensions/ConventionModelExtensions.cs | 6 ++-- src/EFCore/Extensions/EntityTypeExtensions.cs | 8 ++--- src/EFCore/Extensions/ModelExtensions.cs | 3 +- .../Extensions/MutableEntityTypeExtensions.cs | 3 +- .../Extensions/MutableModelExtensions.cs | 3 +- .../Metadata/Internal/CoreAnnotationNames.cs | 9 ------ src/EFCore/Metadata/Internal/EntityType.cs | 29 +++++++++++++++++-- src/EFCore/Metadata/Internal/Model.cs | 28 +++++++++++++++++- 9 files changed, 66 insertions(+), 30 deletions(-) diff --git a/src/EFCore/Extensions/ConventionEntityTypeExtensions.cs b/src/EFCore/Extensions/ConventionEntityTypeExtensions.cs index dd9ce0d576f..6c391e9fec4 100644 --- a/src/EFCore/Extensions/ConventionEntityTypeExtensions.cs +++ b/src/EFCore/Extensions/ConventionEntityTypeExtensions.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -606,8 +607,7 @@ public static IConventionIndex RemoveIndex( [NotNull] this IConventionEntityType entityType, ChangeTrackingStrategy? changeTrackingStrategy, bool fromDataAnnotation = false) - => Check.NotNull(entityType, nameof(entityType)).AsEntityType() - .SetChangeTrackingStrategy( + => ((EntityType)entityType).SetChangeTrackingStrategy( changeTrackingStrategy, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); @@ -616,8 +616,9 @@ public static IConventionIndex RemoveIndex( /// /// The entity type. /// The configuration source for . + [DebuggerStepThrough] public static ConfigurationSource? GetChangeTrackingStrategyConfigurationSource([NotNull] this IConventionEntityType entityType) - => entityType.FindAnnotation(CoreAnnotationNames.ChangeTrackingStrategy)?.GetConfigurationSource(); + => ((EntityType)entityType).GetChangeTrackingStrategyConfigurationSource(); /// /// Sets the LINQ expression filter automatically applied to queries for this entity type. diff --git a/src/EFCore/Extensions/ConventionModelExtensions.cs b/src/EFCore/Extensions/ConventionModelExtensions.cs index 6a2061d3937..68545e8123b 100644 --- a/src/EFCore/Extensions/ConventionModelExtensions.cs +++ b/src/EFCore/Extensions/ConventionModelExtensions.cs @@ -192,8 +192,7 @@ public static IReadOnlyList FindLeastDerivedEntityTypes( [NotNull] this IConventionModel model, ChangeTrackingStrategy? changeTrackingStrategy, bool fromDataAnnotation = false) - => Check.NotNull((Model)model, nameof(model)) - .SetChangeTrackingStrategy( + => ((Model)model).SetChangeTrackingStrategy( changeTrackingStrategy, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); @@ -202,8 +201,9 @@ public static IReadOnlyList FindLeastDerivedEntityTypes( /// /// The model to find configuration source for. /// The configuration source for . + [DebuggerStepThrough] public static ConfigurationSource? GetChangeTrackingStrategyConfigurationSource([NotNull] this IConventionModel model) - => model.FindAnnotation(CoreAnnotationNames.ChangeTrackingStrategy)?.GetConfigurationSource(); + => ((Model)model).GetChangeTrackingStrategyConfigurationSource(); /// /// Returns a value indicating whether the entity types using the given type should be configured diff --git a/src/EFCore/Extensions/EntityTypeExtensions.cs b/src/EFCore/Extensions/EntityTypeExtensions.cs index 5c5b57f7c36..c6e240c9d8f 100644 --- a/src/EFCore/Extensions/EntityTypeExtensions.cs +++ b/src/EFCore/Extensions/EntityTypeExtensions.cs @@ -698,13 +698,9 @@ public static IIndex FindIndex([NotNull] this IEntityType entityType, [NotNull] /// /// The entity type. /// The change tracking strategy. + [DebuggerStepThrough] public static ChangeTrackingStrategy GetChangeTrackingStrategy([NotNull] this IEntityType entityType) - { - Check.NotNull(entityType, nameof(entityType)); - - return (ChangeTrackingStrategy?)entityType[CoreAnnotationNames.ChangeTrackingStrategy] - ?? entityType.Model.GetChangeTrackingStrategy(); - } + => ((EntityType)entityType).GetChangeTrackingStrategy(); /// /// Gets the data stored in the model for the given entity type. diff --git a/src/EFCore/Extensions/ModelExtensions.cs b/src/EFCore/Extensions/ModelExtensions.cs index ecd6bad495c..7d582659135 100644 --- a/src/EFCore/Extensions/ModelExtensions.cs +++ b/src/EFCore/Extensions/ModelExtensions.cs @@ -139,8 +139,7 @@ public static bool IsShared([NotNull] this IModel model, [NotNull] Type type) /// The change tracking strategy. [DebuggerStepThrough] public static ChangeTrackingStrategy GetChangeTrackingStrategy([NotNull] this IModel model) - => (ChangeTrackingStrategy?)Check.NotNull(model, nameof(model))[CoreAnnotationNames.ChangeTrackingStrategy] - ?? ChangeTrackingStrategy.Snapshot; + => ((Model)model).GetChangeTrackingStrategy(); /// /// diff --git a/src/EFCore/Extensions/MutableEntityTypeExtensions.cs b/src/EFCore/Extensions/MutableEntityTypeExtensions.cs index dea33f837d4..42dda10d6ab 100644 --- a/src/EFCore/Extensions/MutableEntityTypeExtensions.cs +++ b/src/EFCore/Extensions/MutableEntityTypeExtensions.cs @@ -549,8 +549,7 @@ public static IMutableIndex RemoveIndex( public static void SetChangeTrackingStrategy( [NotNull] this IMutableEntityType entityType, ChangeTrackingStrategy? changeTrackingStrategy) - => Check.NotNull(entityType, nameof(entityType)).AsEntityType() - .SetChangeTrackingStrategy(changeTrackingStrategy, ConfigurationSource.Explicit); + => ((EntityType)entityType).SetChangeTrackingStrategy(changeTrackingStrategy, ConfigurationSource.Explicit); /// /// Sets the LINQ expression filter automatically applied to queries for this entity type. diff --git a/src/EFCore/Extensions/MutableModelExtensions.cs b/src/EFCore/Extensions/MutableModelExtensions.cs index 24371118172..cd56ea0f04f 100644 --- a/src/EFCore/Extensions/MutableModelExtensions.cs +++ b/src/EFCore/Extensions/MutableModelExtensions.cs @@ -196,8 +196,7 @@ public static void SetPropertyAccessMode( public static void SetChangeTrackingStrategy( [NotNull] this IMutableModel model, ChangeTrackingStrategy? changeTrackingStrategy) - => Check.NotNull((Model)model, nameof(model)) - .SetChangeTrackingStrategy(changeTrackingStrategy, ConfigurationSource.Explicit); + => ((Model)model).SetChangeTrackingStrategy(changeTrackingStrategy, ConfigurationSource.Explicit); /// /// Marks the given entity type as ignored, preventing conventions from adding a matching entity type to the model. diff --git a/src/EFCore/Metadata/Internal/CoreAnnotationNames.cs b/src/EFCore/Metadata/Internal/CoreAnnotationNames.cs index 4c93c4bf7c8..92eb1467cda 100644 --- a/src/EFCore/Metadata/Internal/CoreAnnotationNames.cs +++ b/src/EFCore/Metadata/Internal/CoreAnnotationNames.cs @@ -78,14 +78,6 @@ public static class CoreAnnotationNames /// public const string NavigationAccessMode = "NavigationAccessMode"; - /// - /// 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 ChangeTrackingStrategy = "ChangeTrackingStrategy"; - /// /// 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 @@ -289,7 +281,6 @@ public static class CoreAnnotationNames ValueGeneratorFactory, PropertyAccessMode, NavigationAccessMode, - ChangeTrackingStrategy, OwnedTypes, DiscriminatorProperty, DiscriminatorMappingComplete, diff --git a/src/EFCore/Metadata/Internal/EntityType.cs b/src/EFCore/Metadata/Internal/EntityType.cs index ae15d4ed158..7233917b70e 100644 --- a/src/EFCore/Metadata/Internal/EntityType.cs +++ b/src/EFCore/Metadata/Internal/EntityType.cs @@ -57,10 +57,12 @@ private readonly SortedDictionary _serviceProperties private Key _primaryKey; private bool? _isKeyless; private EntityType _baseType; + private ChangeTrackingStrategy? _changeTrackingStrategy; private ConfigurationSource? _primaryKeyConfigurationSource; private ConfigurationSource? _isKeylessConfigurationSource; private ConfigurationSource? _baseTypeConfigurationSource; + private ConfigurationSource? _changeTrackingStrategyConfigurationSource; // Warning: Never access these fields directly as access needs to be thread-safe private PropertyCounts _counts; @@ -3064,7 +3066,17 @@ public virtual void AddData([NotNull] IEnumerable data) #endregion - #region Annotations + #region Other + + /// + /// 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. + /// + [DebuggerStepThrough] + public virtual ChangeTrackingStrategy GetChangeTrackingStrategy() + => _changeTrackingStrategy ?? Model.GetChangeTrackingStrategy(); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -3086,7 +3098,11 @@ public virtual void AddData([NotNull] IEnumerable data) } } - this.SetOrRemoveAnnotation(CoreAnnotationNames.ChangeTrackingStrategy, changeTrackingStrategy, configurationSource); + _changeTrackingStrategy = changeTrackingStrategy; + + _changeTrackingStrategyConfigurationSource = _changeTrackingStrategy == null + ? (ConfigurationSource?)null + : configurationSource.Max(_changeTrackingStrategyConfigurationSource); return changeTrackingStrategy; } @@ -3131,6 +3147,15 @@ public virtual string CheckChangeTrackingStrategy(ChangeTrackingStrategy value, return null; } + /// + /// 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 ConfigurationSource? GetChangeTrackingStrategyConfigurationSource() + => _changeTrackingStrategyConfigurationSource; + /// /// 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/Metadata/Internal/Model.cs b/src/EFCore/Metadata/Internal/Model.cs index 483446322f3..b5b330b47fa 100644 --- a/src/EFCore/Metadata/Internal/Model.cs +++ b/src/EFCore/Metadata/Internal/Model.cs @@ -62,6 +62,9 @@ private readonly Dictionary _ignoredTypeNames new Dictionary { { DefaultPropertyBagType, ConfigurationSource.Convention } }; private bool? _skipDetectChanges; + private ChangeTrackingStrategy? _changeTrackingStrategy; + + private ConfigurationSource? _changeTrackingStrategyConfigurationSource; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -931,6 +934,16 @@ public virtual void AddShared([NotNull] Type type, ConfigurationSource configura return propertyAccessMode; } + /// + /// 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. + /// + [DebuggerStepThrough] + public virtual ChangeTrackingStrategy GetChangeTrackingStrategy() + => _changeTrackingStrategy ?? ChangeTrackingStrategy.Snapshot; + /// /// 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 @@ -941,11 +954,24 @@ public virtual void AddShared([NotNull] Type type, ConfigurationSource configura ChangeTrackingStrategy? changeTrackingStrategy, ConfigurationSource configurationSource) { - this.SetOrRemoveAnnotation(CoreAnnotationNames.ChangeTrackingStrategy, changeTrackingStrategy, configurationSource); + _changeTrackingStrategy = changeTrackingStrategy; + + _changeTrackingStrategyConfigurationSource = _changeTrackingStrategy == null + ? (ConfigurationSource?)null + : configurationSource.Max(_changeTrackingStrategyConfigurationSource); return changeTrackingStrategy; } + /// + /// 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 ConfigurationSource? GetChangeTrackingStrategyConfigurationSource() + => _changeTrackingStrategyConfigurationSource; + /// /// Runs the conventions when an annotation was set or removed. ///