{"record":{"id":"c4207d6f083ff6d6","repo":"dotnet/efcore","slug":"the-entity-type-entitytype-was-configured-to-u","errorCode":null,"errorMessage":"The entity type '{entityType}' was configured to use some stored procedures and is not mapped to any table. An entity type that isn't mapped to a table must be mapped to insert, update and delete stored procedures.","messagePattern":"The entity type '(.+?)' was configured to use some stored procedures and is not mapped to any table\\. An entity type that isn't mapped to a table must be mapped to insert, update and delete stored procedures\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs","lineNumber":509,"sourceCode":"            ValidateStoredProcedureName(StoreObjectType.InsertStoredProcedure, entityType);\n            ValidateSproc(insertStoredProcedure, mappingStrategy, logger);\n            sprocCount++;\n        }\n\n        var updateStoredProcedure = entityType.GetUpdateStoredProcedure();\n        if (updateStoredProcedure != null)\n        {\n            ValidateStoredProcedureName(StoreObjectType.UpdateStoredProcedure, entityType);\n            ValidateSproc(updateStoredProcedure, mappingStrategy, logger);\n            sprocCount++;\n        }\n\n        if (sprocCount > 0\n            // TODO: Support this with #28703\n            //&& sprocCount < 3\n            && entityType.GetTableName() == null)\n        {\n            throw new InvalidOperationException(RelationalStrings.StoredProcedureUnmapped(entityType.DisplayName()));\n        }\n\n        static void ValidateStoredProcedureName(\n            StoreObjectType storedProcedureType,\n            IEntityType entityType)\n        {\n            var sprocId = StoreObjectIdentifier.Create(entityType, storedProcedureType);\n            if (sprocId == null)\n            {\n                throw new InvalidOperationException(\n                    RelationalStrings.StoredProcedureNoName(\n                        entityType.DisplayName(), storedProcedureType));\n            }\n        }\n    }\n\n    /// <summary>\n    ///     Validates a single stored procedure and all entity types mapped to it.","sourceCodeStart":491,"sourceCodeEnd":527,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs#L491-L527","documentation":"Thrown at the end of ValidateStoredProcedures when at least one CUD stored procedure is configured on the entity (sprocCount > 0) but entityType.GetTableName() is null (RelationalModelValidator.cs:504-510). EF requires that an entity using stored procedures be table-mapped; partial stored-procedure-only mapping is not supported (the TODO at line 505 references issue #28703).","triggerScenarios":"Configuring only one or two of insert/update/delete sprocs (e.g., only Insert) and removing the table mapping. Or calling .ToTable((string)null) / .ToView(\"X\") while still setting .InsertUsingStoredProcedure(...). The validator counts configured sprocs and demands a table name when any exist.","commonSituations":"Switching an entity to a view (ToView) but leaving CUD sproc config from a previous iteration; migrating from ToTable to ToSqlQuery without removing sproc configuration; partial scaffolding that registered insert sproc only.","solutions":["Map the entity to a table: .ToTable(\"TableName\") (or remove .ToView/.ToSqlQuery/null-table overrides).","Provide all three CUD stored procedures if you intend full sproc mapping (the TODO notes partial isn't yet supported — though current code only requires a table name).","Remove the stored-procedure configuration entirely (InsertUsingStoredProcedure / UpdateUsingStoredProcedure / DeleteUsingStoredProcedure) if the entity is read-only or view-backed."],"exampleFix":"// before\nmodelBuilder.Entity<AuditLog>()\n    .ToView(\"vw_AuditLogs\")\n    .InsertUsingStoredProcedure(\"sp_AuditLogInsert\", sp => { /* ... */ });\n\n// after — choose one path\n// Option A: keep sproc, map to table\nmodelBuilder.Entity<AuditLog>()\n    .ToTable(\"AuditLogs\")\n    .InsertUsingStoredProcedure(\"sp_AuditLogInsert\", sp => { /* ... */ })\n    .UpdateUsingStoredProcedure(\"sp_AuditLogUpdate\", sp => { /* ... */ })\n    .DeleteUsingStoredProcedure(\"sp_AuditLogDelete\", sp => { /* ... */ });\n// Option B: read-only, no sprocs\nmodelBuilder.Entity<AuditLog>().ToView(\"vw_AuditLogs\").HasNoKey(); // or ToSqlQuery","handlingStrategy":"validation","validationCode":"foreach (var et in modelBuilder.Model.GetEntityTypes())\n{\n    int n = (et.GetInsertStoredProcedure() is null ? 0 : 1)\n          + (et.GetUpdateStoredProcedure() is null ? 0 : 1)\n          + (et.GetDeleteStoredProcedure() is null ? 0 : 1);\n    if (n > 0 && et.GetTableName() is null)\n        throw new InvalidOperationException($\"Entity '{et.Name}' has {n} sproc(s) but no table mapping; map to a table or remove all sproc config.\");\n}","typeGuard":null,"tryCatchPattern":"try { _ = ctx.Model; }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"not mapped to any table\"))\n{\n    logger.LogError(\"Sproc-mapped entity must be table-mapped. {Msg}\", ex.Message);\n    throw;\n}","preventionTips":["Decide up front whether an entity is view-backed (read-only) or sproc-backed (CUD) — not both.","When switching ToTable to ToView, strip all Insert/Update/DeleteUsingStoredProcedure calls in the same commit.","Add a build-time test that asserts no entity mixes ToView with CUD sprocs."],"tags":["efcore","relational","stored-procedure","entity-mapping","table-mapping","model-validation"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}