From 534ee76f8c4e596a7b81f3d3cf94f8adffed7421 Mon Sep 17 00:00:00 2001 From: AndriySvyryd Date: Thu, 15 Dec 2022 11:36:44 -0800 Subject: [PATCH] Don't validate shared columns have the same provider type unless they are used in a key, foreign key or a unique index Fixes #29859 --- .../RelationalModelValidator.cs | 8 ++- .../RelationalModelValidatorTest.cs | 53 ++++++++++++++++++- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs b/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs index 55c4ea6edf5..152be9c0a67 100644 --- a/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs +++ b/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs @@ -1410,7 +1410,13 @@ protected virtual void ValidateCompatible( ?? typeMapping.ClrType; var previousProviderType = duplicateTypeMapping.Converter?.ProviderClrType.UnwrapNullableType() ?? duplicateTypeMapping.ClrType; - if (currentProviderType != previousProviderType) + if (currentProviderType != previousProviderType + && (property.IsKey() + || duplicateProperty.IsKey() + || property.IsForeignKey() + || duplicateProperty.IsForeignKey() + || (property.IsIndex() && property.GetContainingIndexes().Any(i => i.IsUnique)) + || (duplicateProperty.IsIndex() && duplicateProperty.GetContainingIndexes().Any(i => i.IsUnique)))) { throw new InvalidOperationException( RelationalStrings.DuplicateColumnNameProviderTypeMismatch( diff --git a/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs b/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs index f522a7f6a0e..babe29cae97 100644 --- a/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs +++ b/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs @@ -497,7 +497,7 @@ public virtual void Detects_properties_mapped_to_the_same_column_within_hierarch } [ConditionalFact] - public virtual void Detects_incompatible_shared_columns_in_shared_table_with_different_provider_types() + public virtual void Passes_for_incompatible_shared_columns_in_shared_table_with_different_provider_types() { var modelBuilder = CreateConventionModelBuilder(); @@ -507,6 +507,57 @@ public virtual void Detects_incompatible_shared_columns_in_shared_table_with_dif modelBuilder.Entity().Property(b => b.P0).HasColumnName(nameof(A.P0)).HasColumnType("someInt"); modelBuilder.Entity().ToTable("Table"); + Validate(modelBuilder); + } + + [ConditionalFact] + public virtual void Detects_incompatible_shared_columns_in_shared_table_with_different_provider_types_for_unique_indexes() + { + var modelBuilder = CreateConventionModelBuilder(); + + modelBuilder.Entity().HasOne().WithOne(b => b.A).HasForeignKey(a => a.Id).HasPrincipalKey(b => b.Id).IsRequired(); + modelBuilder.Entity().Property(a => a.P0).HasColumnName(nameof(A.P0)).HasColumnType("someInt").HasConversion(); + modelBuilder.Entity().ToTable("Table"); + modelBuilder.Entity().Property(b => b.P0).HasColumnName(nameof(A.P0)).HasColumnType("someInt"); + modelBuilder.Entity().ToTable("Table"); + modelBuilder.Entity().HasIndex(a => a.P0).IsUnique(); + + VerifyError( + RelationalStrings.DuplicateColumnNameProviderTypeMismatch( + nameof(A), nameof(A.P0), nameof(B), nameof(B.P0), nameof(B.P0), "Table", "long", "int"), + modelBuilder); + } + + [ConditionalFact] + public virtual void Detects_incompatible_shared_columns_in_shared_table_with_different_provider_types_for_keys() + { + var modelBuilder = CreateConventionModelBuilder(); + + modelBuilder.Entity().HasOne().WithOne(b => b.A).HasForeignKey(a => a.Id).HasPrincipalKey(b => b.Id).IsRequired(); + modelBuilder.Entity().Property(a => a.P0).HasColumnName(nameof(A.P0)).HasColumnType("someInt").HasConversion(); + modelBuilder.Entity().ToTable("Table"); + modelBuilder.Entity().Property(b => b.P0).HasColumnName(nameof(A.P0)).HasColumnType("someInt"); + modelBuilder.Entity().ToTable("Table"); + modelBuilder.Entity().HasAlternateKey(a => a.P0); + + VerifyError( + RelationalStrings.DuplicateColumnNameProviderTypeMismatch( + nameof(A), nameof(A.P0), nameof(B), nameof(B.P0), nameof(B.P0), "Table", "long", "int"), + modelBuilder); + } + + [ConditionalFact] + public virtual void Detects_incompatible_shared_columns_in_shared_table_with_different_provider_types_for_foreign_keys() + { + var modelBuilder = CreateConventionModelBuilder(); + + modelBuilder.Entity().HasOne().WithOne(b => b.A).HasForeignKey(a => a.Id).HasPrincipalKey(b => b.Id).IsRequired(); + modelBuilder.Entity().Property(a => a.P0).HasColumnName(nameof(A.P0)).HasColumnType("someInt").HasConversion(); + modelBuilder.Entity().ToTable("Table"); + modelBuilder.Entity().Property(b => b.P0).HasColumnName(nameof(A.P0)).HasColumnType("someInt"); + modelBuilder.Entity().ToTable("Table"); + modelBuilder.Entity().HasOne().WithOne().HasForeignKey(a => a.P0).HasPrincipalKey(b => b.Id); + VerifyError( RelationalStrings.DuplicateColumnNameProviderTypeMismatch( nameof(A), nameof(A.P0), nameof(B), nameof(B.P0), nameof(B.P0), "Table", "long", "int"),