{"record":{"id":"9dfaeea02cf7421c","repo":"dotnet/efcore","slug":"the-entity-type-dependenttype-is-mapped-to-s","errorCode":null,"errorMessage":"The entity type '{dependentType}' is mapped to '{storeObject}'. However the principal entity type '{principalEntityType}' is also mapped to '{storeObject}' and it's using the TPC mapping strategy. Entity types in a TPC hierarchy can use table-sharing only if they have no derived types.","messagePattern":"The entity type '(.+?)' is mapped to '(.+?)'\\. However the principal entity type '(.+?)' is also mapped to '(.+?)' and it's using the TPC mapping strategy\\. Entity types in a TPC hierarchy can use table-sharing only if they have no derived types\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs","lineNumber":2264,"sourceCode":"                            RelationalStrings.NonTphViewClash(\n                                entityType.DisplayName(), otherType.DisplayName(), storeObject.Value.DisplayName()));\n                    case StoreObjectType.InsertStoredProcedure:\n                    case StoreObjectType.DeleteStoredProcedure:\n                    case StoreObjectType.UpdateStoredProcedure:\n                        throw new InvalidOperationException(\n                            RelationalStrings.NonTphStoredProcedureClash(\n                                entityType.DisplayName(), otherType.DisplayName(), storeObject.Value.DisplayName()));\n                }\n            }\n\n            if (isTpc)\n            {\n                var rowInternalFk = entityType.FindDeclaredReferencingRowInternalForeignKeys(storeObject.Value)\n                    .FirstOrDefault();\n                if (rowInternalFk != null\n                    && entityType.GetDirectlyDerivedTypes().Any())\n                {\n                    throw new InvalidOperationException(\n                        RelationalStrings.TpcTableSharing(\n                            rowInternalFk.DeclaringEntityType.DisplayName(),\n                            storeObject.Value.DisplayName(),\n                            rowInternalFk.PrincipalEntityType.DisplayName()));\n                }\n            }\n\n            derivedTypes[storeObject.Value] = entityType;\n        }\n\n        var rootStoreObject = StoreObjectIdentifier.Create(rootEntityType, storeObjectType);\n        if (rootStoreObject == null)\n        {\n            return;\n        }\n\n        if (rootEntityType.FindRowInternalForeignKeys(rootStoreObject.Value).Any()\n            && derivedTypes.Count > 1","sourceCodeStart":2246,"sourceCodeEnd":2282,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs#L2246-L2282","documentation":"Thrown inside ValidateNonTphMapping when, under the TPC strategy, an entity type has a row internal foreign key (meaning it shares a table with its principal via table splitting) AND that same entity type has directly derived types. TPC permits table sharing only for leaf types that have no derived types, because a shared table cannot be replicated per concrete type.","triggerScenarios":"A TPC hierarchy where an intermediate (non-leaf) type participates in table sharing (FindDeclaredReferencingRowInternalForeignKeys returns a key) and also has GetDirectlyDerivedTypes().Any() == true.","commonSituations":"Combining owned/table-splitting with a TPC hierarchy on a base type that is itself inherited from; converting a splitting scenario into TPC; an intermediate entity that owns another entity and is derived from.","solutions":["Move the table sharing onto a leaf type (a type with no derived types).","Remove the inheritance from the type that shares a table so it becomes a leaf.","Switch the hierarchy away from TPC, or stop table-sharing on the non-leaf type."],"exampleFix":"// before (TPC, non-leaf shares table)\nmodelBuilder.UseTpcMappingStrategy();\nmodelBuilder.Entity<Person>().OwnsOne(p => p.Contact, c => c.ToTable(\"People\"));\n// Person has derived types -> throws 429\n\n// after - share on a leaf only, or stop splitting the non-leaf\nmodelBuilder.Entity<Customer>().OwnsOne(p => p.Contact, c => c.ToTable(\"Customers\"));","handlingStrategy":"validation","validationCode":"foreach (var root in modelBuilder.Model.GetEntityTypes().Where(t => t.BaseType == null))\n{\n    if (root.GetMappingStrategy() != RelationalAnnotationNames.TpcMappingStrategy) continue;\n    foreach (var et in root.GetDerivedTypesInclusive())\n    {\n        if (!et.GetDirectlyDerivedTypes().Any()) continue;\n        foreach (StoreObjectType sot in new[] { StoreObjectType.Table, StoreObjectType.View })\n        {\n            var so = StoreObjectIdentifier.Create(et, sot);\n            if (so == null) continue;\n            if (et.FindDeclaredReferencingRowInternalForeignKeys(so.Value).Any())\n                throw new InvalidOperationException($\"{et.DisplayName()} shares a {sot} but has derived types under TPC.\");\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not place table sharing on non-leaf types in a TPC hierarchy.","Move ownership/splitting to leaf types, or stop sharing the table.","Test the model build after combining TPC with owned/split types."],"tags":["ef-core","model-validation","mapping","inheritance","tpc","table-splitting","owned-types"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}