dotnet/efcore · error · InvalidOperationException
The operation '{operation}' is being applied on entity type
Error message
The operation '{operation}' is being applied on entity type '{entityType}', which uses entity splitting. 'ExecuteDelete'/'ExecuteUpdate' operations on entity types using entity splitting are not supported. What it means
TranslateExecuteDelete requires exactly one table mapping; the default arm of the switch throws when entityType.GetTableMappings() returns more than one mapping, i.e. the entity is split across multiple tables (entity splitting via multiple .ToTable calls mapping different properties). A single parametrized DELETE cannot update all split tables atomically, so ExecuteDelete/ExecuteUpdate are refused.
Source
Thrown at src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteDelete.cs:48
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)
{
// In normal cases, the table expression will be refer to the same table model we found above for the entity type.
if (unwrappedTableExpression.Table is ITable)
{View on GitHub (pinned to 3a2006ef56)
Solutions
- Consolidate the entity into a single table mapping (remove the splitting ToTable calls).
- Load entities and use RemoveRange + SaveChanges so EF deletes from each split table correctly.
- Issue raw SQL DELETEs against each split table in the correct order.
Example fix
// before (entity splitting -> 595)
modelBuilder.Entity<Customer>()
.ToTable("customers")
.SplitToTable("customer_details", t => t.Property(c => c.Notes));
await db.Customers.Where(c => c.Archived).ExecuteDeleteAsync();
// after (single table, or use SaveChanges)
await db.Customers.Where(c => c.Archived).ExecuteDeleteAsync(); // after removing SplitToTable Defensive patterns
Strategy: validation
Validate before calling
// Refuse ExecuteDelete/ExecuteUpdate on entities with multiple table mappings (splitting).
var et = db.Model.FindEntityType(typeof(TEntity))!;
var tableCount = et.GetTableMappings().Select(m => m.Table).Distinct().Count();
if (tableCount > 1)
throw new InvalidOperationException(
$"{et.Name} uses entity splitting ({tableCount} tables); bulk delete/update is unsupported. Use SaveChanges or raw SQL."); Prevention
- Avoid entity splitting for entities that need bulk delete/update.
- Prefer SaveChanges for split entities so EF coordinates multi-table writes.
- Document which entities are split so developers know to avoid ExecuteDelete/ExecuteUpdate.
When it happens
Trigger: ExecuteDelete/ExecuteUpdate on an entity configured with entity splitting, e.g. modelBuilder.Entity<T>().ToTable("t_main") and a second ToTable mapping a subset of properties to "t_extra"; executing the bulk operation triggers the multi-mapping arm.
Common situations: Legacy models using entity splitting for column count limits; refactoring a wide table into a main + extension table and expecting existing ExecuteDelete calls to keep working.
Related errors
- '{operation}' used over owned type '{entityType}' which is m
- The operation '{operation}' is being applied on entity type
- The operation '{operation}' is being applied on entity type
- The operation 'ExecuteDelete' is being applied on the table
- The operation 'ExecuteDelete' requires an entity type which
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/636ee629304b5d12.
Report an issue: GitHub.