dotnet/efcore · error · InvalidOperationException
ExecuteUpdateDeleteOnEntityNotMappedToTable
ExecuteUpdateDeleteOnEntityNotMappedToTable
Error message
'ExecuteUpdate' or 'ExecuteDelete' was called on entity type '{entityType}', but that entity type is not mapped to a table. What it means
Thrown when ExecuteDelete/ExecuteUpdate is applied to an entity type that has no table mappings at all (GetTableMappings returns empty). Bulk DML needs a real table to modify; entities mapped only to views (or not mapped to any table) cannot be bulk-updated.
Source
Thrown at src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteDelete.cs:45
{
case RelationalAnnotationNames.TptMappingStrategy:
throw new InvalidOperationException(
RelationalStrings.ExecuteOperationOnTPT(
nameof(EntityFrameworkQueryableExtensions.ExecuteDelete),
entityType.DisplayName()));
// Note that we do allow TPC if the target is a leaf type
case RelationalAnnotationNames.TpcMappingStrategy when entityType.GetDirectlyDerivedTypes().Any():
throw new InvalidOperationException(
RelationalStrings.ExecuteOperationOnTPC(
nameof(EntityFrameworkQueryableExtensions.ExecuteDelete),
entityType.DisplayName()));
}
// Find the table model that maps to the entity type; there must be exactly one (e.g. no entity splitting).
var targetTable = entityType.GetTableMappings().ToList() switch
{
[] => throw new InvalidOperationException(
RelationalStrings.ExecuteUpdateDeleteOnEntityNotMappedToTable(entityType.DisplayName())),
[var singleTableMapping] => singleTableMapping.Table,
_ => throw new InvalidOperationException(
RelationalStrings.ExecuteOperationOnEntitySplitting(
nameof(EntityFrameworkQueryableExtensions.ExecuteDelete), entityType.DisplayName())),
};
var selectExpression = (SelectExpression)source.QueryExpression;
// Find the table expression in the SelectExpression that corresponds to the projected entity type.
var projectionBindingExpression = (ProjectionBindingExpression)shaper.ValueBufferExpression;
var projection = (StructuralTypeProjectionExpression)selectExpression.GetProjection(projectionBindingExpression);
var column = projection.BindProperty(shaper.StructuralType.GetProperties().First());
var tableExpression = selectExpression.GetTable(column, out var tableIndex);
// If the projected table expression (the thing to be deleted) isn't a TableExpression (e.g. it's a set operation), we can't
// translate to a simple DELETE (which requires a simple target table), and must fall back to rewriting as a subquery.
if (tableExpression.UnwrapJoin() is TableExpression unwrappedTableExpression)
{View on GitHub (pinned to dbf9771522)
Solutions
- Map the entity type to a table with ToTable so bulk DML has a target.
- For view-backed read-only entities, perform deletes/updates via raw SQL against the underlying tables using Database.ExecuteSqlRaw.
- Use the change tracker only if a table mapping exists; otherwise restructure so a table backs the entity.
- Review the model: ensure ToTable is present (or remove ToView-only mapping) for types you intend to mutate.
Example fix
// before
modelBuilder.Entity<ReportRow>().ToView("v_Report");
await db.ReportRows.ExecuteDeleteAsync();
// after - map to the underlying table
modelBuilder.Entity<ReportRow>().ToTable("ReportRows");
await db.ReportRows.ExecuteDeleteAsync();
// or use raw SQL against the backing table
await db.Database.ExecuteSqlRawAsync("DELETE FROM ReportRows WHERE ..."); Defensive patterns
Strategy: validation
Validate before calling
var hasTable = entityType.GetTableMappings().Any();
if (!hasTable)
throw new InvalidOperationException($"{entityType.Name} is not mapped to a table; bulk ops need a ToTable mapping."); Try / catch
try { await db.ReportRows.ExecuteDeleteAsync(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("not mapped to a table"))
{
await db.Database.ExecuteSqlRawAsync("DELETE FROM ReportRows WHERE ...");
} Prevention
- Ensure ToTable is set for any entity you bulk-modify.
- Treat ToView-only entities as read-only.
- Use raw SQL for deletes/updates on view-backed types.
- Audit the model for types missing table mappings.
When it happens
Trigger: Calling ExecuteDelete/ExecuteUpdate on an entity configured with ToView(nameof(View)) and no ToTable, a keyless query type mapped to a view, or an entity type with no relational mapping.
Common situations: Mapping read-only entities to database views and then attempting bulk delete/update; denormalized query-only models; entities that back caches or computed views.
Related errors
- ExecuteOperationOnOwnedJsonIsNotSupported
- ExecuteOperationOnTPT
- ExecuteOperationOnTPC
- ExecuteOperationOnEntitySplitting
- ExecuteUpdateDeleteOnEntityNotMappedToTable
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/61a8dca1468663aa.
Report an issue: GitHub.