dotnet/efcore · error · InvalidOperationException
The entity type ' ' was configured to use some stored…
Error message
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. What it means
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).
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.
Example fix
// before
modelBuilder.Entity<AuditLog>()
.ToView("vw_AuditLogs")
.InsertUsingStoredProcedure("sp_AuditLogInsert", sp => { /* ... */ });
// after — choose one path
// Option A: keep sproc, map to table
modelBuilder.Entity<AuditLog>()
.ToTable("AuditLogs")
.InsertUsingStoredProcedure("sp_AuditLogInsert", sp => { /* ... */ })
.UpdateUsingStoredProcedure("sp_AuditLogUpdate", sp => { /* ... */ })
.DeleteUsingStoredProcedure("sp_AuditLogDelete", sp => { /* ... */ });
// Option B: read-only, no sprocs
modelBuilder.Entity<AuditLog>().ToView("vw_AuditLogs").HasNoKey(); // or ToSqlQuery Defensive patterns
Strategy: validation
Validate before calling
foreach (var et in modelBuilder.Model.GetEntityTypes())
{
int n = (et.GetInsertStoredProcedure() is null ? 0 : 1)
+ (et.GetUpdateStoredProcedure() is null ? 0 : 1)
+ (et.GetDeleteStoredProcedure() is null ? 0 : 1);
if (n > 0 && et.GetTableName() is null)
throw new InvalidOperationException($"Entity '{et.Name}' has {n} sproc(s) but no table mapping; map to a table or remove all sproc config.");
} Try / catch
try { _ = ctx.Model; }
catch (InvalidOperationException ex) when (ex.Message.Contains("not mapped to any table"))
{
logger.LogError("Sproc-mapped entity must be table-mapped. {Msg}", ex.Message);
throw;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Both entity type ' ' and ' ' were configured to use ' '…
- The entity type ' ' was configured to use ' ', but the…
- The keyless entity type
- Current value parameter
- Input parameter ' ' of insert stored procedure ' ' is…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/c4207d6f083ff6d6.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:509
ValidateStoredProcedureName(StoreObjectType.InsertStoredProcedure, entityType);
ValidateSproc(insertStoredProcedure, mappingStrategy, logger);
sprocCount++;
}
var updateStoredProcedure = entityType.GetUpdateStoredProcedure();
if (updateStoredProcedure != null)
{
ValidateStoredProcedureName(StoreObjectType.UpdateStoredProcedure, entityType);
ValidateSproc(updateStoredProcedure, mappingStrategy, logger);
sprocCount++;
}
if (sprocCount > 0
// TODO: Support this with #28703
//&& sprocCount < 3
&& entityType.GetTableName() == null)
{
throw new InvalidOperationException(RelationalStrings.StoredProcedureUnmapped(entityType.DisplayName()));
}
static void ValidateStoredProcedureName(
StoreObjectType storedProcedureType,
IEntityType entityType)
{
var sprocId = StoreObjectIdentifier.Create(entityType, storedProcedureType);
if (sprocId == null)
{
throw new InvalidOperationException(
RelationalStrings.StoredProcedureNoName(
entityType.DisplayName(), storedProcedureType));
}
}
}
/// <summary>
/// Validates a single stored procedure and all entity types mapped to it.View on GitHub (pinned to 3a2006ef56)