{"record":{"id":"e63649aab6e86d07","repo":"dotnet/efcore","slug":"the-mapping-strategy-mappingstrategy-used-for","errorCode":null,"errorMessage":"The mapping strategy '{mappingStrategy}' used for '{entityType}' is not supported for keyless entity types.  See https://go.microsoft.com/fwlink/?linkid=2130430 for more information.","messagePattern":"The mapping strategy '(.+?)' used for '(.+?)' is not supported for keyless entity types\\.  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":2122,"sourceCode":"                    RelationalStrings.NonTphMappingStrategy(mappingStrategy, entityType.DisplayName()));\n            }\n\n            ValidateTphMapping(entityType, StoreObjectType.Table);\n            ValidateTphMapping(entityType, StoreObjectType.View);\n            ValidateTphMapping(entityType, StoreObjectType.Function);\n            ValidateTphMapping(entityType, StoreObjectType.InsertStoredProcedure);\n            ValidateTphMapping(entityType, StoreObjectType.DeleteStoredProcedure);\n            ValidateTphMapping(entityType, StoreObjectType.UpdateStoredProcedure);\n\n            ValidateDiscriminatorValues(entityType);\n        }\n        else\n        {\n            if (mappingStrategy != RelationalAnnotationNames.TpcMappingStrategy\n                && entityType.FindPrimaryKey() == null\n                && entityType.GetDirectlyDerivedTypes().Any())\n            {\n                throw new InvalidOperationException(\n                    RelationalStrings.KeylessMappingStrategy(\n                        mappingStrategy ?? RelationalAnnotationNames.TptMappingStrategy, entityType.DisplayName()));\n            }\n\n            ValidateNonTphMapping(entityType, StoreObjectType.Table);\n            ValidateNonTphMapping(entityType, StoreObjectType.View);\n            ValidateNonTphMapping(entityType, StoreObjectType.InsertStoredProcedure);\n            ValidateNonTphMapping(entityType, StoreObjectType.DeleteStoredProcedure);\n            ValidateNonTphMapping(entityType, StoreObjectType.UpdateStoredProcedure);\n\n            var derivedTypes = entityType.GetDerivedTypesInclusive().ToList();\n            var discriminatorValues = new Dictionary<string, IEntityType>();\n            foreach (var derivedType in derivedTypes)\n            {\n                foreach (var complexProperty in derivedType.GetDeclaredComplexProperties())\n                {\n                    ValidateDiscriminatorValues(complexProperty.ComplexType);\n                }","sourceCodeStart":2104,"sourceCodeEnd":2140,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs#L2104-L2140","documentation":"Thrown during hierarchy validation when an entity type has no primary key (is keyless), has one or more derived types, and the hierarchy is not using the TPC mapping strategy. TPT/TPH inheritance requires each type to have a primary key so the rows can be linked/resolved, so a keyless type in a non-TPC hierarchy is illegal. Note the message defaults the strategy to TPT when it is null.","triggerScenarios":"A keyless entity type (HasNoKey) that is the base of an inheritance hierarchy while the mapping strategy is TPH (default) or TPT, i.e. FindPrimaryKey() == null && GetDirectlyDerivedTypes().Any() && strategy != TPC.","commonSituations":"Using a keyless query result type as a base for other types; forgetting a [Key] or HasKey on the base of a hierarchy; mixing owned/keyless concepts with inheritance; switching a hierarchy to include a keyless view-backed type.","solutions":["Define a primary key on the entity with HasKey(...) or a [Key] attribute.","If the type must stay keyless, use TPC: modelBuilder.UseTpcMappingStrategy() — the only strategy that tolerates keyless types in a hierarchy.","Remove the inheritance relationship (make the derived types standalone) if a key is genuinely impossible."],"exampleFix":"// before\nmodelBuilder.Entity<KeylessBase>().HasNoKey();\nmodelBuilder.Entity<Derived : KeylessBase>();\n// default TPH strategy -> throws 421\n\n// after (add a key)\nmodelBuilder.Entity<KeylessBase>().HasKey(x => x.Id);\n// or use TPC\n// modelBuilder.UseTpcMappingStrategy();","handlingStrategy":"validation","validationCode":"foreach (var entityType in modelBuilder.Model.GetEntityTypes())\n{\n    var strategy = entityType.GetMappingStrategy();\n    var isKeyless = entityType.FindPrimaryKey() == null;\n    var hasDerived = entityType.GetDirectlyDerivedTypes().Any();\n    if (isKeyless && hasDerived\n        && strategy != RelationalAnnotationNames.TpcMappingStrategy)\n    {\n        throw new InvalidOperationException($\"{entityType.DisplayName()} is keyless with derived types; add a key or use TPC.\");\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never use HasNoKey() on a base type of an inheritance hierarchy unless the hierarchy is TPC.","Run a model-build test that catches keyless+inheritance misconfigurations before deployment.","Audit [Key]/HasKey usage whenever introducing inheritance."],"tags":["ef-core","model-validation","mapping","inheritance","keyless","tpc","tpt"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}