{"record":{"id":"527bc2b7621e53f8","repo":"dotnet/efcore","slug":"executeoperationonentitysplitting","errorCode":"ExecuteOperationOnEntitySplitting","errorMessage":"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.","messagePattern":"The operation '(.+?)' is being applied on entity type '(.+?)', which uses entity splitting\\. 'ExecuteDelete'/'ExecuteUpdate' operations on entity types using entity splitting are not supported\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteDelete.cs","lineNumber":48,"sourceCode":"                    RelationalStrings.ExecuteOperationOnTPT(\n                        nameof(EntityFrameworkQueryableExtensions.ExecuteDelete),\n                        entityType.DisplayName()));\n\n            // Note that we do allow TPC if the target is a leaf type\n            case RelationalAnnotationNames.TpcMappingStrategy when entityType.GetDirectlyDerivedTypes().Any():\n                throw new InvalidOperationException(\n                    RelationalStrings.ExecuteOperationOnTPC(\n                        nameof(EntityFrameworkQueryableExtensions.ExecuteDelete),\n                        entityType.DisplayName()));\n        }\n\n        // Find the table model that maps to the entity type; there must be exactly one (e.g. no entity splitting).\n        var targetTable = entityType.GetTableMappings().ToList() switch\n        {\n            [] => throw new InvalidOperationException(\n                RelationalStrings.ExecuteUpdateDeleteOnEntityNotMappedToTable(entityType.DisplayName())),\n            [var singleTableMapping] => singleTableMapping.Table,\n            _ => throw new InvalidOperationException(\n                RelationalStrings.ExecuteOperationOnEntitySplitting(\n                    nameof(EntityFrameworkQueryableExtensions.ExecuteDelete), entityType.DisplayName())),\n        };\n        var selectExpression = (SelectExpression)source.QueryExpression;\n\n        // Find the table expression in the SelectExpression that corresponds to the projected entity type.\n        var projectionBindingExpression = (ProjectionBindingExpression)shaper.ValueBufferExpression;\n        var projection = (StructuralTypeProjectionExpression)selectExpression.GetProjection(projectionBindingExpression);\n        var column = projection.BindProperty(shaper.StructuralType.GetProperties().First());\n        var tableExpression = selectExpression.GetTable(column, out var tableIndex);\n\n        // If the projected table expression (the thing to be deleted) isn't a TableExpression (e.g. it's a set operation), we can't\n        // translate to a simple DELETE (which requires a simple target table), and must fall back to rewriting as a subquery.\n        if (tableExpression.UnwrapJoin() is TableExpression unwrappedTableExpression)\n        {\n            // In normal cases, the table expression will be refer to the same table model we found above for the entity type.\n            if (unwrappedTableExpression.Table is ITable)\n            {","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteDelete.cs#L30-L66","documentation":"Thrown by TranslateExecuteDelete when the target entity type has more than one table mapping - i.e. it uses entity splitting (an entity spread across multiple tables via multiple ToTable calls). ExecuteDelete cannot safely modify multiple tables in one DML statement, so it is rejected.","triggerScenarios":"Configuring an entity with entity splitting: modelBuilder.Entity<Customer>().ToTable(\"Customers\").SplitToTable(t => t.Property(c => c.Details), \"CustomerDetails\") or multiple ToTable calls, then calling ExecuteDelete on that entity.","commonSituations":"Performance-motivated entity splitting (wide tables split vertically) combined with bulk delete attempts; legacy schemas forcing splits.","solutions":["Remove the entity splitting so the entity maps to a single table, then ExecuteDelete works.","Load the entities and delete via SaveChanges, which correctly issues deletes across all split tables.","Issue separate ExecuteSqlRaw deletes against each split table keyed by the entity key.","Restructure the model (e.g. move split-off columns into owned/complex types) so bulk DML is supported."],"exampleFix":"// before - entity splitting\nmodelBuilder.Entity<Customer>()\n    .ToTable(\"Customers\")\n    .SplitToTable(\"CustomerDetails\", t => t.MapKey(c => c.Id));\nawait db.Customers.Where(c => c.Id == id).ExecuteDeleteAsync();\n// after - single table mapping\nmodelBuilder.Entity<Customer>().ToTable(\"Customers\");\nawait db.Customers.Where(c => c.Id == id).ExecuteDeleteAsync();\n// or tracked delete across splits\nvar c = await db.Customers.FindAsync(id);\ndb.Customers.Remove(c);\nawait db.SaveChangesAsync();","handlingStrategy":"validation","validationCode":"var tableCount = entityType.GetTableMappings().Count();\nif (tableCount > 1)\n    throw new InvalidOperationException($\"{entityType.Name} uses entity splitting; ExecuteDelete unsupported.\");","typeGuard":null,"tryCatchPattern":"try { await db.Customers.Where(c => c.Id == id).ExecuteDeleteAsync(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"entity splitting\"))\n{\n    var c = await db.Customers.FindAsync(id);\n    db.Customers.Remove(c);\n    await db.SaveChangesAsync();\n}","preventionTips":["Avoid entity splitting for types you need to bulk-delete.","Use SaveChanges for split entities (it handles multiple tables).","Move wide/seldom-used columns to owned or complex types instead of split tables.","Document split entities as excluded from ExecuteDelete."],"tags":["executedelete","entity-splitting","table-mapping","bulk-operations"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}