{"record":{"id":"636ee629304b5d12","repo":"dotnet/efcore","slug":"the-operation-operation-is-being-applied-on-en-636ee6","errorCode":null,"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/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteDelete.cs#L30-L66","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (entity splitting -> 595)\nmodelBuilder.Entity<Customer>()\n    .ToTable(\"customers\")\n    .SplitToTable(\"customer_details\", t => t.Property(c => c.Notes));\nawait db.Customers.Where(c => c.Archived).ExecuteDeleteAsync();\n// after (single table, or use SaveChanges)\nawait db.Customers.Where(c => c.Archived).ExecuteDeleteAsync(); // after removing SplitToTable","handlingStrategy":"validation","validationCode":"// Refuse ExecuteDelete/ExecuteUpdate on entities with multiple table mappings (splitting).\nvar et = db.Model.FindEntityType(typeof(TEntity))!;\nvar tableCount = et.GetTableMappings().Select(m => m.Table).Distinct().Count();\nif (tableCount > 1)\n    throw new InvalidOperationException(\n        $\"{et.Name} uses entity splitting ({tableCount} tables); bulk delete/update is unsupported. Use SaveChanges or raw SQL.\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["efcore","executedelete","entity-splitting","mapping"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}