{"record":{"id":"fc8747274a91fd8f","repo":"dotnet/efcore","slug":"executeoperationwithunsupportedoperatorinsqlgenera","errorCode":"ExecuteOperationWithUnsupportedOperatorInSqlGeneration","errorMessage":"The operation '{operation}' contains a select expression feature that isn't supported in the query SQL generator, but has been declared as supported by provider during translation phase. This is a bug in your EF Core provider, file an issue at https://aka.ms/efcorefeedback.","messagePattern":"The operation '(.+?)' contains a select expression feature that isn't supported in the query SQL generator, but has been declared as supported by provider during translation phase\\. This is a bug in your EF Core provider, file an issue at https://aka\\.ms/efcorefeedback\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Query/QuerySqlGenerator.cs","lineNumber":231,"sourceCode":"                Orderings: [],\n                Offset: null,\n                Limit: null\n            }\n            && table.Equals(deleteExpression.Table))\n        {\n            _relationalCommandBuilder.Append(\"DELETE FROM \");\n            Visit(deleteExpression.Table);\n\n            if (selectExpression.Predicate != null)\n            {\n                _relationalCommandBuilder.AppendLine().Append(\"WHERE \");\n                Visit(selectExpression.Predicate);\n            }\n\n            return deleteExpression;\n        }\n\n        throw new InvalidOperationException(\n            RelationalStrings.ExecuteOperationWithUnsupportedOperatorInSqlGeneration(\n                nameof(EntityFrameworkQueryableExtensions.ExecuteDelete)));\n    }\n\n    /// <summary>\n    ///     Generates SQL for a SELECT expression.\n    /// </summary>\n    /// <param name=\"selectExpression\">The <see cref=\"SelectExpression\" /> for which to generate SQL.</param>\n    protected virtual Expression VisitSelect(SelectExpression selectExpression)\n    {\n        IDisposable? subQueryIndent = null;\n        if (selectExpression.Alias != null)\n        {\n            _relationalCommandBuilder.AppendLine(\"(\");\n            subQueryIndent = _relationalCommandBuilder.Indent();\n        }\n\n        if (!TryGenerateWithoutWrappingSelect(selectExpression))","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Query/QuerySqlGenerator.cs#L213-L249","documentation":"Thrown by QuerySqlGenerator.VisitDelete (QuerySqlGenerator.cs:231) when an ExecuteDelete (bulk delete) operation's SelectExpression contains a feature the SQL generator cannot render as a simple DELETE (e.g. multiple tables, GROUP BY/HAVING, OFFSET/LIMIT, ordering, or projections). The translation phase marked the operation as supported, but SQL generation finds it isn't, which the message calls out as a provider bug. (The error text references ExecuteDelete specifically.)","triggerScenarios":"Calling ExecuteDelete on a query whose translated SelectExpression is more complex than a single-table DELETE with an optional WHERE (e.g. deleting via a JOIN, after grouping, with a limit, or with projections). The translation layer accepted it, but VisitDelete only handles {single table, no group/having/projection/order/offset/limit}.","commonSituations":"ExecuteDelete over a query with Include/Join (multi-table), GroupBy, Distinct, Skip/Take, or a subquery that produces a non-simple select; using ExecuteDelete where the predicate requires joining; provider declaring more support than it can generate.","solutions":["Rewrite ExecuteDelete to target a single table with a simple predicate; precompute the keys to delete and delete by primary key.","Move filtering into a simple Where on the entity's own columns so the SelectExpression reduces to one table + WHERE.","If a JOIN is needed, first select the keys into a list, then ExecuteDelete on keys (e.g. Where(e => keys.Contains(e.Id))).","If you maintain a provider, extend VisitDelete (or restrict translation) so declared support matches generatable SQL; report via the feedback link."],"exampleFix":"// before - ExecuteDelete over a join/group cannot be rendered\nawait ctx.Orders\n    .Where(o => o.Customer.Region == \"EU\") // forces a JOIN -> unsupported\n    .ExecuteDeleteAsync();\n\n// after - reduce to a single-table predicate, or delete by precomputed keys\nvar ids = ctx.Orders\n    .Where(o => o.Customer.Region == \"EU\")\n    .Select(o => o.Id).ToList();\nawait ctx.Orders.Where(o => ids.Contains(o.Id)).ExecuteDeleteAsync();","handlingStrategy":"validation","validationCode":"// Reduce ExecuteDelete to a single-table predicate before calling it.\n// If filtering requires related data, precompute keys and delete by key.\nvar ids = ctx.Orders.Where(o => o.Customer.Region == \"EU\").Select(o => o.Id).ToList();\nawait ctx.Orders.Where(o => ids.Contains(o.Id)).ExecuteDeleteAsync();","typeGuard":null,"tryCatchPattern":"try { await ctx.Orders.Where(predicate).ExecuteDeleteAsync(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"select expression feature that isn't supported\")) {\n    // ExecuteDelete can't render this select; delete by precomputed keys instead.\n    var ids = ctx.Orders.Where(predicate).Select(o => o.Id).ToList();\n    await ctx.Orders.Where(o => ids.Contains(o.Id)).ExecuteDeleteAsync();\n}","preventionTips":["Use ExecuteDelete only against a single table with a simple WHERE on its own columns.","When filtering needs related data, precompute keys and delete by primary key.","Avoid ExecuteDelete over joins, groupings, distinct, or limit clauses.","Provider authors: keep declared translation support in sync with generatable SQL."],"tags":["ef-core","execute-delete","bulk-operations","sql-generation","provider"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}