diff --git a/EFCore.NamingConventions.Test/NameRewritingConventionTest.cs b/EFCore.NamingConventions.Test/NameRewritingConventionTest.cs index 73d0ff7..9a54209 100644 --- a/EFCore.NamingConventions.Test/NameRewritingConventionTest.cs +++ b/EFCore.NamingConventions.Test/NameRewritingConventionTest.cs @@ -157,6 +157,75 @@ namespace EFCore.NamingConventions.Test Assert.Equal("PK_parent", childKey.GetName()); } + [Fact] + public void TPH_with_owned() + { + var model = BuildModel(b => + { + b.Entity(); + b.Entity().OwnsOne(c => c.Owned); + }); + + var parentEntityType = model.FindEntityType(typeof(Parent)); + var childEntityType = model.FindEntityType(typeof(ChildWithOwned)); + var ownedEntityType = model.FindEntityType(typeof(Owned)); + + Assert.Equal("parent", parentEntityType.GetTableName()); + Assert.Equal("id", parentEntityType.FindProperty(nameof(Parent.Id)) + .GetColumnName(StoreObjectIdentifier.Create(parentEntityType, StoreObjectType.Table)!.Value)); + Assert.Equal("parent_property", parentEntityType.FindProperty(nameof(Parent.ParentProperty)) + .GetColumnName(StoreObjectIdentifier.Create(childEntityType, StoreObjectType.Table)!.Value)); + + Assert.Equal("parent", childEntityType.GetTableName()); + Assert.Equal("child_property", childEntityType.FindProperty(nameof(Child.ChildProperty)) + .GetColumnName(StoreObjectIdentifier.Create(childEntityType, StoreObjectType.Table)!.Value)); + + Assert.Same(parentEntityType.FindPrimaryKey(), childEntityType.FindPrimaryKey()); + + Assert.Equal("parent", ownedEntityType.GetTableName()); + Assert.Equal("owned_owned_property", ownedEntityType.FindProperty(nameof(Owned.OwnedProperty)) + .GetColumnName(StoreObjectIdentifier.Create(ownedEntityType, StoreObjectType.Table)!.Value)); + } + + [Fact] + public void TPT_with_owned() + { + var model = BuildModel(b => + { + b.Entity().ToTable("parent"); + b.Entity( + e => + { + e.ToTable("child"); + e.OwnsOne(c => c.Owned); + }); + }); + + var parentEntityType = model.FindEntityType(typeof(Parent)); + var childEntityType = model.FindEntityType(typeof(ChildWithOwned)); + var ownedEntityType = model.FindEntityType(typeof(Owned)); + + Assert.Equal("parent", parentEntityType.GetTableName()); + Assert.Equal("id", parentEntityType.FindProperty(nameof(Parent.Id)) + .GetColumnName(StoreObjectIdentifier.Create(parentEntityType, StoreObjectType.Table)!.Value)); + Assert.Equal("parent_property", parentEntityType.FindProperty(nameof(Parent.ParentProperty)) + .GetColumnName(StoreObjectIdentifier.Create(parentEntityType, StoreObjectType.Table)!.Value)); + + Assert.Equal("child", childEntityType.GetTableName()); + Assert.Equal("child_property", childEntityType.FindProperty(nameof(ChildWithOwned.ChildProperty)) + .GetColumnName(StoreObjectIdentifier.Create(childEntityType, StoreObjectType.Table)!.Value)); + + var parentKey = parentEntityType.FindPrimaryKey(); + var childKey = childEntityType.FindPrimaryKey(); + + Assert.Equal("PK_parent", parentKey.GetName()); + Assert.Equal("PK_parent", childKey.GetName()); + + Assert.Equal("child", ownedEntityType.GetTableName()); + Assert.Equal("owned_owned_property", ownedEntityType.FindProperty(nameof(Owned.OwnedProperty)) + .GetColumnName(StoreObjectIdentifier.Create(ownedEntityType, StoreObjectType.Table)!.Value)); + } + [Fact] public void Table_splitting() { @@ -281,6 +350,12 @@ namespace EFCore.NamingConventions.Test public int ChildProperty { get; set; } } + public class ChildWithOwned : Parent + { + public int ChildProperty { get; set; } + public Owned Owned { get; set; } + } + public class Split1 { public int Id { get; set; } diff --git a/EFCore.NamingConventions/Internal/NameRewritingConvention.cs b/EFCore.NamingConventions/Internal/NameRewritingConvention.cs index f2ccd0c..20c1a09 100644 --- a/EFCore.NamingConventions/Internal/NameRewritingConvention.cs +++ b/EFCore.NamingConventions/Internal/NameRewritingConvention.cs @@ -4,6 +4,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Conventions; +using Microsoft.EntityFrameworkCore.Metadata.Internal; namespace EFCore.NamingConventions.Internal { @@ -94,20 +95,36 @@ namespace EFCore.NamingConventions.Internal public void ProcessEntityTypeAnnotationChanged(IConventionEntityTypeBuilder entityTypeBuilder, string name, IConventionAnnotation annotation, IConventionAnnotation oldAnnotation, IConventionContext context) { - if (name != RelationalAnnotationNames.TableName) + var entityType = entityTypeBuilder.Metadata; + + if (name != RelationalAnnotationNames.TableName + || StoreObjectIdentifier.Create(entityType, StoreObjectType.Table) is not StoreObjectIdentifier tableIdentifier) { return; } - var entityType = entityTypeBuilder.Metadata; - // The table's name is changing - rewrite keys, index names + if (entityType.FindPrimaryKey() is IConventionKey primaryKey) { - if (entityType.BaseType is not null - && entityType.GetTableName() != entityType.BaseType.GetTableName()) + // We need to rewrite the PK name. + // However, this isn't yet supported with TPT, see https://github.com/dotnet/efcore/issues/23444. + // So we need to check if the entity is within a TPT hierarchy, or is an owned entity within a TPT hierarchy. + var tempEntityType = (IEntityType)entityType; + while (true) + { + var foreignKey = tempEntityType.FindRowInternalForeignKeys(tableIdentifier).FirstOrDefault(); + if (foreignKey is null) + { + break; + } + + tempEntityType = foreignKey.PrincipalEntityType; + } + + if (tempEntityType.BaseType is not null + && tempEntityType.GetTableName() != tempEntityType.BaseType.GetTableName()) { - // It's not yet possible to set the PK name with TPT, see https://github.com/dotnet/efcore/issues/23444. primaryKey.Builder.HasNoAnnotation(RelationalAnnotationNames.Name); } else