Skip to content

Commit

Permalink
Don't use PropertyInfo from unmapped base type
Browse files Browse the repository at this point in the history
Fixes #22092
  • Loading branch information
AndriySvyryd committed Aug 25, 2020
1 parent e3a2651 commit c6ef53f
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 24 deletions.
47 changes: 45 additions & 2 deletions src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -510,8 +510,7 @@ private InternalPropertyBuilder Property(
entityType = existingProperty.DeclaringEntityType;
}

var existingMember = existingProperty.GetIdentifyingMemberInfo();
if ((memberInfo == null || existingMember.IsOverridenBy(memberInfo))
if (IsCompatible(memberInfo, existingProperty)
&& (propertyType == null || propertyType == existingProperty.ClrType))
{
if (configurationSource.HasValue)
Expand Down Expand Up @@ -699,6 +698,50 @@ private InternalPropertyBuilder Property(
: builder;
}

private bool IsCompatible(MemberInfo newMemberInfo, Property existingProperty)
{
if (newMemberInfo == null)
{
return true;
}

var existingMemberInfo = existingProperty.GetIdentifyingMemberInfo();
if (existingMemberInfo == null)
{
return false;
}

if (newMemberInfo == existingMemberInfo)
{
return true;
}

var declaringType = (IMutableEntityType)existingProperty.DeclaringType;
if (!newMemberInfo.DeclaringType.IsAssignableFrom(declaringType.ClrType))
{
return existingMemberInfo.IsOverridenBy(newMemberInfo);
}

IMutableEntityType existingMemberDeclaringEntityType = null;
foreach (var baseType in declaringType.GetAllBaseTypes())
{
if (newMemberInfo.DeclaringType == baseType.ClrType)
{
return existingMemberDeclaringEntityType != null
&& existingMemberInfo.IsOverridenBy(newMemberInfo);
}

if (existingMemberDeclaringEntityType == null
&& existingMemberInfo.DeclaringType == baseType.ClrType)
{
existingMemberDeclaringEntityType = baseType;
}
}

// newMemberInfo is declared on an unmapped base type, existingMemberInfo should be kept
return newMemberInfo.IsOverridenBy(existingMemberInfo);
}

private bool CanRemoveProperty(
[NotNull] Property property,
ConfigurationSource configurationSource,
Expand Down
1 change: 1 addition & 0 deletions test/EFCore.Specification.Tests/DataAnnotationTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2501,6 +2501,7 @@ protected class One : OneBase
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("Unique_No")]
public override int UniqueNo { get; set; }

[ConcurrencyCheck]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,11 @@ public override ModelBuilder DatabaseGeneratedOption_configures_the_property_cor
public virtual void ColumnAttribute_configures_the_property_correctly()
{
var modelBuilder = CreateModelBuilder();
modelBuilder.Entity<One>();
modelBuilder.Entity<One>().HasKey(o => o.UniqueNo);

Assert.Equal(
"Name",
modelBuilder.Model.FindEntityType(typeof(One)).FindProperty(nameof(One.RequiredColumn)).GetColumnName());
"Unique_No",
modelBuilder.Model.FindEntityType(typeof(One)).FindProperty(nameof(One.UniqueNo)).GetColumnName());
}

public override ModelBuilder DatabaseGeneratedOption_Identity_does_not_throw_on_noninteger_properties()
Expand All @@ -159,13 +159,13 @@ public override void ConcurrencyCheckAttribute_throws_if_value_in_database_chang
base.ConcurrencyCheckAttribute_throws_if_value_in_database_changed();

AssertSql(
@"SELECT TOP(1) [s].[UniqueNo], [s].[MaxLengthProperty], [s].[Name], [s].[RowVersion], [s].[AdditionalDetails_Name], [s].[Details_Name]
@"SELECT TOP(1) [s].[Unique_No], [s].[MaxLengthProperty], [s].[Name], [s].[RowVersion], [s].[AdditionalDetails_Name], [s].[Details_Name]
FROM [Sample] AS [s]
WHERE [s].[UniqueNo] = 1",
WHERE [s].[Unique_No] = 1",
//
@"SELECT TOP(1) [s].[UniqueNo], [s].[MaxLengthProperty], [s].[Name], [s].[RowVersion], [s].[AdditionalDetails_Name], [s].[Details_Name]
@"SELECT TOP(1) [s].[Unique_No], [s].[MaxLengthProperty], [s].[Name], [s].[RowVersion], [s].[AdditionalDetails_Name], [s].[Details_Name]
FROM [Sample] AS [s]
WHERE [s].[UniqueNo] = 1",
WHERE [s].[Unique_No] = 1",
//
@"@p2='1'
@p0='ModifiedData' (Nullable = false) (Size = 4000)
Expand All @@ -174,7 +174,7 @@ FROM [Sample] AS [s]
SET NOCOUNT ON;
UPDATE [Sample] SET [Name] = @p0, [RowVersion] = @p1
WHERE [UniqueNo] = @p2 AND [RowVersion] = @p3;
WHERE [Unique_No] = @p2 AND [RowVersion] = @p3;
SELECT @@ROWCOUNT;",
//
@"@p2='1'
Expand All @@ -184,7 +184,7 @@ FROM [Sample] AS [s]
SET NOCOUNT ON;
UPDATE [Sample] SET [Name] = @p0, [RowVersion] = @p1
WHERE [UniqueNo] = @p2 AND [RowVersion] = @p3;
WHERE [Unique_No] = @p2 AND [RowVersion] = @p3;
SELECT @@ROWCOUNT;");
}

Expand All @@ -202,9 +202,9 @@ public override void DatabaseGeneratedAttribute_autogenerates_values_when_set_to
SET NOCOUNT ON;
INSERT INTO [Sample] ([MaxLengthProperty], [Name], [RowVersion], [AdditionalDetails_Name], [Details_Name])
VALUES (@p0, @p1, @p2, @p3, @p4);
SELECT [UniqueNo]
SELECT [Unique_No]
FROM [Sample]
WHERE @@ROWCOUNT = 1 AND [UniqueNo] = scope_identity();");
WHERE @@ROWCOUNT = 1 AND [Unique_No] = scope_identity();");
}

public override void MaxLengthAttribute_throws_while_inserting_value_longer_than_max_length()
Expand All @@ -221,9 +221,9 @@ public override void MaxLengthAttribute_throws_while_inserting_value_longer_than
SET NOCOUNT ON;
INSERT INTO [Sample] ([MaxLengthProperty], [Name], [RowVersion], [AdditionalDetails_Name], [Details_Name])
VALUES (@p0, @p1, @p2, @p3, @p4);
SELECT [UniqueNo]
SELECT [Unique_No]
FROM [Sample]
WHERE @@ROWCOUNT = 1 AND [UniqueNo] = scope_identity();",
WHERE @@ROWCOUNT = 1 AND [Unique_No] = scope_identity();",
//
@"@p0='VeryVeryVeryVeryVeryVeryLongString' (Size = 4000)
@p1='ValidString' (Nullable = false) (Size = 4000)
Expand All @@ -234,9 +234,9 @@ FROM [Sample]
SET NOCOUNT ON;
INSERT INTO [Sample] ([MaxLengthProperty], [Name], [RowVersion], [AdditionalDetails_Name], [Details_Name])
VALUES (@p0, @p1, @p2, @p3, @p4);
SELECT [UniqueNo]
SELECT [Unique_No]
FROM [Sample]
WHERE @@ROWCOUNT = 1 AND [UniqueNo] = scope_identity();");
WHERE @@ROWCOUNT = 1 AND [Unique_No] = scope_identity();");
}

public override void StringLengthAttribute_throws_while_inserting_value_longer_than_max_length()
Expand Down
14 changes: 7 additions & 7 deletions test/EFCore.Sqlite.FunctionalTests/DataAnnotationSqliteTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,14 @@ public override void ConcurrencyCheckAttribute_throws_if_value_in_database_chang
base.ConcurrencyCheckAttribute_throws_if_value_in_database_changed();

AssertSql(
@"SELECT ""s"".""UniqueNo"", ""s"".""MaxLengthProperty"", ""s"".""Name"", ""s"".""RowVersion"", ""s"".""AdditionalDetails_Name"", ""s"".""Details_Name""
@"SELECT ""s"".""Unique_No"", ""s"".""MaxLengthProperty"", ""s"".""Name"", ""s"".""RowVersion"", ""s"".""AdditionalDetails_Name"", ""s"".""Details_Name""
FROM ""Sample"" AS ""s""
WHERE ""s"".""UniqueNo"" = 1
WHERE ""s"".""Unique_No"" = 1
LIMIT 1",
//
@"SELECT ""s"".""UniqueNo"", ""s"".""MaxLengthProperty"", ""s"".""Name"", ""s"".""RowVersion"", ""s"".""AdditionalDetails_Name"", ""s"".""Details_Name""
@"SELECT ""s"".""Unique_No"", ""s"".""MaxLengthProperty"", ""s"".""Name"", ""s"".""RowVersion"", ""s"".""AdditionalDetails_Name"", ""s"".""Details_Name""
FROM ""Sample"" AS ""s""
WHERE ""s"".""UniqueNo"" = 1
WHERE ""s"".""Unique_No"" = 1
LIMIT 1",
//
@"@p2='1' (DbType = String)
Expand All @@ -113,7 +113,7 @@ public override void ConcurrencyCheckAttribute_throws_if_value_in_database_chang
@p3='00000001-0000-0000-0000-000000000001' (DbType = String)
UPDATE ""Sample"" SET ""Name"" = @p0, ""RowVersion"" = @p1
WHERE ""UniqueNo"" = @p2 AND ""RowVersion"" = @p3;
WHERE ""Unique_No"" = @p2 AND ""RowVersion"" = @p3;
SELECT changes();",
//
@"@p2='1' (DbType = String)
Expand All @@ -122,7 +122,7 @@ public override void ConcurrencyCheckAttribute_throws_if_value_in_database_chang
@p3='00000001-0000-0000-0000-000000000001' (DbType = String)
UPDATE ""Sample"" SET ""Name"" = @p0, ""RowVersion"" = @p1
WHERE ""UniqueNo"" = @p2 AND ""RowVersion"" = @p3;
WHERE ""Unique_No"" = @p2 AND ""RowVersion"" = @p3;
SELECT changes();");
}

Expand All @@ -139,7 +139,7 @@ public override void DatabaseGeneratedAttribute_autogenerates_values_when_set_to
INSERT INTO ""Sample"" (""MaxLengthProperty"", ""Name"", ""RowVersion"", ""AdditionalDetails_Name"", ""Details_Name"")
VALUES (@p0, @p1, @p2, @p3, @p4);
SELECT ""UniqueNo""
SELECT ""Unique_No""
FROM ""Sample""
WHERE changes() = 1 AND ""rowid"" = last_insert_rowid();");
}
Expand Down

0 comments on commit c6ef53f

Please sign in to comment.