{"record":{"id":"43d7e930fc1b0474","repo":"dotnet/efcore","slug":"the-operation-operation-is-being-applied-on-en-43d7e9","errorCode":null,"errorMessage":"The operation '{operation}' is being applied on entity type '{entityType}', which is using the TPC mapping strategy and is not a leaf type. 'ExecuteDelete'/'ExecuteUpdate' operations on entity types participating in TPC hierarchies is only supported for leaf types.","messagePattern":"The operation '(.+?)' is being applied on entity type '(.+?)', which is using the TPC mapping strategy and is not a leaf type\\. 'ExecuteDelete'/'ExecuteUpdate' operations on entity types participating in TPC hierarchies is only supported for leaf types\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteDelete.cs","lineNumber":36,"sourceCode":"        }\n\n        if (entityType.IsMappedToJson())\n        {\n            throw new InvalidOperationException(\n                RelationalStrings.ExecuteOperationOnOwnedJsonIsNotSupported(\"ExecuteDelete\", entityType.DisplayName()));\n        }\n\n        switch (entityType.GetMappingStrategy())\n        {\n            case RelationalAnnotationNames.TptMappingStrategy:\n                throw new InvalidOperationException(\n                    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.","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteDelete.cs#L18-L54","documentation":"TranslateExecuteDelete allows TPC only for leaf types. This throw fires for a TPC-mapped entity that has directly derived types (non-leaf), because deleting a non-leaf TPC type would have to delete from multiple concrete tables and there is no single table that represents the abstract type. Leaf types map to exactly one table and are safe.","triggerScenarios":"context.Set<TpcAbstract>().ExecuteDelete() where TpcAbstract is mapped with .UseTpcMappingStrategy() and has derived types; targeting an intermediate abstract type in a TPC hierarchy.","commonSituations":"Bulk-deleting against a TPC root or intermediate node; assuming ExecuteDelete on a base type fans out to all subtype tables.","solutions":["Target each concrete leaf subtype separately, or query for instances and use RemoveRange + SaveChanges.","Restructure the query so it filters to a single leaf type before ExecuteDelete.","If you must delete across the hierarchy, issue raw SQL deletes against each concrete table.","Reconsider TPC if hierarchy-wide bulk operations are common."],"exampleFix":"// before (TPC non-leaf)\nawait db.Set<TpcBase>().Where(b => b.Stale).ExecuteDeleteAsync();\n// after (per leaf type)\nawait db.Set<TpcLeafA>().Where(b => b.Stale).ExecuteDeleteAsync();\nawait db.Set<TpcLeafB>().Where(b => b.Stale).ExecuteDeleteAsync();","handlingStrategy":"validation","validationCode":"// Only allow ExecuteDelete on TPC leaf types.\nvar et = db.Model.FindEntityType(typeof(TEntity))!;\nif (et.GetMappingStrategy() == RelationalAnnotationNames.TpcMappingStrategy\n    && et.GetDirectlyDerivedTypes().Any())\n{\n    throw new InvalidOperationException(\n        $\"{et.Name} is a non-leaf TPC type; target a concrete leaf subtype for ExecuteDelete.\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Target concrete leaf subtypes for bulk operations in TPC hierarchies.","Expose helper methods that fan out ExecuteDelete across leaf types.","Add tests covering each leaf type rather than the abstract root."],"tags":["efcore","executedelete","tpc","inheritance","mapping"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}