{"record":{"id":"a26c1dd50aedfa71","repo":"dotnet/efcore","slug":"entitytype-is-mapped-to-the-table-table-wh","errorCode":null,"errorMessage":"'{entityType}' is mapped to the table '{table}' while '{otherEntityType}' is mapped to the table '{otherTable}'. Map all the entity types in the hierarchy to the same table, or remove the discriminator and map them all to different tables. See https://go.microsoft.com/fwlink/?linkid=2130430 for more information.","messagePattern":"'(.+?)' is mapped to the table '(.+?)' while '(.+?)' is mapped to the table '(.+?)'\\. Map all the entity types in the hierarchy to the same table, or remove the discriminator and map them all to different tables\\. See https://go\\.microsoft\\.com/fwlink/\\?linkid=2130430 for more information\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs","lineNumber":2330,"sourceCode":"                if (rootSproc != null)\n                {\n                    var sproc = StoredProcedure.FindDeclaredStoredProcedure(entityType, storeObjectType);\n                    if (sproc != null\n                        && sproc != rootSproc)\n                    {\n                        throw new InvalidOperationException(\n                            RelationalStrings.StoredProcedureTphDuplicate(\n                                entityType.DisplayName(), rootEntityType.DisplayName(), rootId?.DisplayName()));\n                    }\n                }\n\n                continue;\n            }\n\n            switch (storeObjectType)\n            {\n                case StoreObjectType.Table:\n                    throw new InvalidOperationException(\n                        RelationalStrings.TphTableMismatch(\n                            entityType.DisplayName(), entityId.Value.DisplayName(),\n                            rootEntityType.DisplayName(), rootId?.DisplayName()));\n                case StoreObjectType.View:\n                    throw new InvalidOperationException(\n                        RelationalStrings.TphViewMismatch(\n                            entityType.DisplayName(), entityId.Value.DisplayName(),\n                            rootEntityType.DisplayName(), rootId?.DisplayName()));\n                case StoreObjectType.Function:\n                    throw new InvalidOperationException(\n                        RelationalStrings.TphDbFunctionMismatch(\n                            entityType.DisplayName(), entityId.Value.DisplayName(),\n                            rootEntityType.DisplayName(), rootId?.DisplayName()));\n                case StoreObjectType.InsertStoredProcedure:\n                case StoreObjectType.DeleteStoredProcedure:\n                case StoreObjectType.UpdateStoredProcedure:\n                    throw new InvalidOperationException(\n                        RelationalStrings.TphStoredProcedureMismatch(","sourceCodeStart":2312,"sourceCodeEnd":2348,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs#L2312-L2348","documentation":"Thrown inside ValidateTphMapping when a derived entity type resolves to a different Table StoreObjectIdentifier than the root (entityId != rootId). TPH requires the entire hierarchy to share a single table, so any derived type mapped to another table breaks the invariant.","triggerScenarios":"A TPH hierarchy where a derived type calls ToTable(\"OtherTable\") or is otherwise mapped to a different table than the root; default convention overridden per type.","commonSituations":"Adding ToTable on a derived type while staying on TPH; partial migration to TPT that forgot UseTptMappingStrategy; view-backed read models pulled into a TPH hierarchy.","solutions":["Remove the ToTable override on the derived type so it inherits the root's table.","Switch the whole hierarchy to TPT (UseTptMappingStrategy) if different tables are intended.","Map the root to the same table as the derived types so they all match."],"exampleFix":"// before (TPH but derived type on different table)\nmodelBuilder.Entity<Person>().ToTable(\"People\");\nmodelBuilder.Entity<Customer>().ToTable(\"Customers\"); // throws 432\n\n// after (intended different tables -> TPT)\nmodelBuilder.UseTptMappingStrategy();\nmodelBuilder.Entity<Person>().ToTable(\"People\");\nmodelBuilder.Entity<Customer>().ToTable(\"Customers\");","handlingStrategy":"validation","validationCode":"foreach (var root in modelBuilder.Model.GetEntityTypes().Where(t => t.BaseType == null))\n{\n    if (root.FindDiscriminatorProperty() == null) continue; // not TPH\n    var rootSo = StoreObjectIdentifier.Create(root, StoreObjectType.Table);\n    if (rootSo == null) continue;\n    foreach (var et in root.GetDerivedTypes())\n    {\n        var so = StoreObjectIdentifier.Create(et, StoreObjectType.Table);\n        if (so != null && so.Value != rootSo.Value)\n            throw new InvalidOperationException($\"{et.DisplayName()} maps to {so.Value.DisplayName()} but root maps to {rootSo.Value.DisplayName()} (TPH).\");\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["In TPH, do not call ToTable on derived types.","If different tables are needed, switch to TPT with UseTptMappingStrategy().","Add a model test asserting all derived types share the root's table under TPH."],"tags":["ef-core","model-validation","mapping","inheritance","tph","tables"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}