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
In ProcessColumn (line 438-502), when the table expression does not reference an ITable (e.g. it points at a view or a query-defining expression), EF looks up the corresponding mutable table column for the property. If no such column/table mapping exists (targetColumnModel is null at line 483), ExecuteUpdate/ExecuteDelete cannot target any table and throws ExecuteUpdateDeleteOnEntityNotMappedToTable.
Source
Thrown at src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs:485
// See #28520 about improving this.
var containerColumnName = complexType.GetContainerColumnName();
if (containerColumnName != null)
{
targetColumnModel = complexType.GetTableMappings()
.Select(m => m.Table.FindColumn(containerColumnName))
.SingleOrDefault(c => c is not null);
}
break;
}
default:
throw new UnreachableException();
}
if (targetColumnModel is null)
{
throw new InvalidOperationException(
RelationalStrings.ExecuteUpdateDeleteOnEntityNotMappedToTable(targetProperty.DeclaringType.DisplayName()));
}
unwrappedTableExpression = new TableExpression(unwrappedTableExpression.Alias, targetColumnModel.Table);
tableExpression = tableExpression is JoinExpressionBase join
? join.Update(unwrappedTableExpression)
: unwrappedTableExpression;
var newTables = select.Tables.ToList();
newTables[tableIndex] = tableExpression;
// Note that we need to keep the select mutable, because if IsValidSelectExpressionForExecuteDelete below
// returns false, we need to compose on top of it.
select.SetTables(newTables);
}
CheckColumnOnSameTable(column, propertySelector);
}
View on GitHub (pinned to dbf9771522)
Solutions
- Map the entity to a real table with ToTable so it has a mutable table mapping.
- If the entity is genuinely a view, perform the update against the underlying base table entity or via raw SQL.
- Remove ToView and let EF map by convention to a table, or add an explicit ToTable.
Example fix
// before (entity mapped only to a view)
modelBuilder.Entity<OrderView>().ToView("OrderView").HasNoKey();
db.Set<OrderView>().Where(o => o.Stale)
.ExecuteDelete();
// after (map to a real table so a mutation target exists)
modelBuilder.Entity<OrderView>().ToTable("OrderView");
db.Set<OrderView>().Where(o => o.Stale)
.ExecuteDelete(); Defensive patterns
Strategy: validation
Validate before calling
// Verify the entity has a table mapping (not only a view) before mutating.
foreach (var t in entityType.GetTableMappings()) { /* ok: has a table */ return; }
throw new InvalidOperationException("Entity is not mapped to a table; ExecuteUpdate/ExecuteDelete will fail."); Try / catch
try { await q.ExecuteDeleteAsync(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("not mapped to a table"))
{ /* add ToTable mapping, or target the base table entity / raw SQL */ } Prevention
- Use ToTable (not just ToView) for entities you intend to mutate.
- Reserve HasNoKey/ToView for read-only projections.
- After scaffolding, verify view entities are not used in ExecuteUpdate/ExecuteDelete.
When it happens
Trigger: Calling ExecuteUpdate or ExecuteDelete on an entity type that is mapped only to a view (ToView, no ToTable), to a function, or to a query (HasNoKey + defining query), so GetTableMappings yields no ITable and no mutable column can be found.
Common situations: Read-only view entities mistakenly used for bulk updates; entities configured with ToView instead of ToTable; defining queries (ToQuery) entities; database-first scaffolding that produced view-only mappings.
Related errors
- ExecuteUpdateDeleteOnEntityNotMappedToTable
- The foreign keys {foreignKeyProperties1} on '{entityType1}'
- The foreign keys {foreignKeyProperties1} on '{entityType1}'
- ExecuteOperationOnOwnedJsonIsNotSupported
- ExecuteOperationOnTPT
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/b087417c4389fa36.
Report an issue: GitHub.