From 3ff4d5937ce0c51088de38580b75d136d6a953ef Mon Sep 17 00:00:00 2001 From: lajones Date: Wed, 3 Jun 2020 15:26:52 -0700 Subject: [PATCH] Fix for 21041. All concurrency properties can store store-generated values. (#21128) Make all concurrency properties capable of storing "store-generated values". --- .../Conventions/TableSharingConcurrencyTokenConvention.cs | 4 ++-- src/EFCore.Relational/Update/ModificationCommand.cs | 3 +-- src/EFCore/Metadata/Internal/PropertyExtensions.cs | 3 ++- .../Infrastructure/RelationalModelValidatorTest.cs | 5 ++++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/EFCore.Relational/Metadata/Conventions/TableSharingConcurrencyTokenConvention.cs b/src/EFCore.Relational/Metadata/Conventions/TableSharingConcurrencyTokenConvention.cs index 0b081eed053..ae0cc06717b 100644 --- a/src/EFCore.Relational/Metadata/Conventions/TableSharingConcurrencyTokenConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/TableSharingConcurrencyTokenConvention.cs @@ -107,6 +107,7 @@ public virtual void ProcessModelFinalizing( !exampleProperty.IsNullable).Builder; concurrencyShadowPropertyBuilder .HasColumnName(concurrencyColumnName) + .HasColumnType(exampleProperty.GetColumnType()) ?.IsConcurrencyToken(true) ?.ValueGenerated(exampleProperty.ValueGenerated); #pragma warning restore EF1001 // Internal EF Core API usage. @@ -141,8 +142,7 @@ private void GetMappings(IConventionModel model, foreach (var property in entityType.GetDeclaredProperties()) { - if (property.IsConcurrencyToken - && (property.ValueGenerated & ValueGenerated.OnUpdate) != 0) + if (property.IsConcurrencyToken) { if (!concurrencyColumnsToProperties.TryGetValue(table, out var columnToProperties)) { diff --git a/src/EFCore.Relational/Update/ModificationCommand.cs b/src/EFCore.Relational/Update/ModificationCommand.cs index abaed740eeb..36cf71ed47f 100644 --- a/src/EFCore.Relational/Update/ModificationCommand.cs +++ b/src/EFCore.Relational/Update/ModificationCommand.cs @@ -457,8 +457,7 @@ public bool TryPropagate(IProperty property, IUpdateEntry entry) || (entry.EntityState == EntityState.Modified && !entry.IsModified(property)) || (entry.EntityState == EntityState.Added && Equals(_originalValue, entry.GetCurrentValue(property))))) { - // Should be `entry.SetStoreGeneratedValue(property, _currentValue);` but see issue #21041 - ((InternalEntityEntry)entry)[property] = _currentValue; + entry.SetStoreGeneratedValue(property, _currentValue); return false; } diff --git a/src/EFCore/Metadata/Internal/PropertyExtensions.cs b/src/EFCore/Metadata/Internal/PropertyExtensions.cs index db5138cad4c..9a046503721 100644 --- a/src/EFCore/Metadata/Internal/PropertyExtensions.cs +++ b/src/EFCore/Metadata/Internal/PropertyExtensions.cs @@ -112,7 +112,8 @@ public static bool RequiresValueGenerator([NotNull] this IProperty property) /// public static bool MayBeStoreGenerated([NotNull] this IProperty property) { - if (property.ValueGenerated != ValueGenerated.Never) + if (property.ValueGenerated != ValueGenerated.Never + || property.IsConcurrencyToken) { return true; } diff --git a/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs b/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs index 1541d52ed5f..76cf2e372a3 100644 --- a/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs +++ b/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs @@ -448,7 +448,10 @@ public virtual void Detects_duplicate_column_names_within_hierarchy_with_differe VerifyError( RelationalStrings.DuplicateColumnNameConcurrencyTokenMismatch( - nameof(Cat), nameof(Cat.Breed), nameof(Dog), nameof(Dog.Breed), nameof(Cat.Breed), nameof(Animal)), modelBuilder.Model); + nameof(Animal), "_TableSharingConcurrencyTokenConvention_Breed", + nameof(Dog), nameof(Dog.Breed), + nameof(Cat.Breed), nameof(Animal)), + modelBuilder.Model); } [ConditionalFact]