{"record":{"id":"87a8df59cc837cb6","repo":"dotnet/efcore","slug":"executeupdate-is-being-used-over-a-linq-operator","errorCode":null,"errorMessage":"'ExecuteUpdate' is being used over a LINQ operator which isn't natively supported by the database; this cannot be translated because complex type '{complexType}' is projected out. Rewrite your query to project out the containing entity type instead.","messagePattern":"'ExecuteUpdate' is being used over a LINQ operator which isn't natively supported by the database; this cannot be translated because complex type '(.+?)' is projected out\\. Rewrite your query to project out the containing entity type instead\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs","lineNumber":92,"sourceCode":"            // the first property selector.\n\n            // The following mechanism for extracting the entity type from property selectors only supports simple member access,\n            // EF.Function, etc. We also unwrap casts to interface/base class (#29618). Note that owned IncludeExpressions have already\n            // been pruned from the source before remapping the lambda (#28727).\n            var firstPropertySelector = setters[0].PropertySelector;\n            if (!IsMemberAccess(\n                    RemapLambdaBody(source, firstPropertySelector).UnwrapTypeConversion(out _),\n                    RelationalDependencies.Model,\n                    out var baseExpression)\n                || _sqlTranslator.TranslateProjection(baseExpression) is not StructuralTypeShaperExpression shaper)\n            {\n                throw new InvalidOperationException(RelationalStrings.InvalidPropertyInSetProperty(firstPropertySelector));\n            }\n\n            // TODO: #36336\n            if (shaper.StructuralType is not IEntityType entityType)\n            {\n                throw new InvalidOperationException(\n                    RelationalStrings.ExecuteUpdateSubqueryNotSupportedOverComplexTypes(shaper.StructuralType.DisplayName()));\n            }\n\n            if (entityType.FindPrimaryKey() is not { } pk)\n            {\n                throw new InvalidOperationException(\n                    RelationalStrings.ExecuteOperationOnKeylessEntityTypeWithUnsupportedOperator(\n                        nameof(EntityFrameworkQueryableExtensions.ExecuteUpdate),\n                        entityType.DisplayName()));\n            }\n\n            // Generate the INNER JOIN around the original query, on the PK properties.\n            var outer = (ShapedQueryExpression)Visit(new EntityQueryRootExpression(entityType));\n            var inner = source;\n            var outerParameter = Expression.Parameter(entityType.ClrType);\n            var outerKeySelector = Expression.Lambda(outerParameter.CreateKeyValuesExpression(pk.Properties), outerParameter);\n            var firstPropertyLambdaExpression = setters[0].PropertySelector;\n            var entitySource = GetEntitySource(RelationalDependencies.Model, firstPropertyLambdaExpression.Body);","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs#L74-L110","documentation":"Thrown when ExecuteUpdate is called over a query whose projection yields a complex type instead of an entity type. The translator needs an entity type (with a primary key) to generate the INNER JOIN that wires the bulk update back to the target table; a complex type has no PK and cannot be joined, so the translation aborts. This is tracked under issue #36336 (TODO in source).","triggerScenarios":"Calling ExecuteUpdate/ExecuteUpdateAsync on a query that projects out a complex type (e.g. context.Set<Root>().Select(r => r.Address).ExecuteUpdate(s => s.SetProperty(a => a.City, ...))) where Address is a complex type. Also occurs in complex-table-splitting or complex-JSON bulk update tests where the selector unwraps to a StructuralTypeShaperExpression whose StructuralType is IComplexType rather than IEntityType.","commonSituations":"Migrating from owned types to complex types and keeping ExecuteUpdate calls unchanged; projecting the complex property directly instead of the owning entity; using complex-JSON mappings that surface the complex type as the shaper.","solutions":["Rewrite the query so ExecuteUpdate operates over the owning entity type and reach into the complex property via the entity (e.g. context.Set<Root>().ExecuteUpdate(s => s.SetProperty(r => r.Address.City, ...))).","If you genuinely need to update only complex-type columns, keep the entity as the query root and reference complex members through it so the shaper stays an IEntityType.","Avoid projecting the complex type out of the query with Select before calling ExecuteUpdate."],"exampleFix":"// before\nawait ctx.Set<Root>()\n    .Select(r => r.Address)\n    .ExecuteUpdateAsync(s => s.SetProperty(a => a.City, \"x\"));\n// after\nawait ctx.Set<Root>()\n    .ExecuteUpdateAsync(s => s.SetProperty(r => r.Address.City, \"x\"));","handlingStrategy":"validation","validationCode":"// Before ExecuteUpdate, ensure the query projects an entity, not a complex type.\nExpression<Func<IQueryable<Root>>> rootQuery = () => ctx.Set<Root>();\n// Build the query from a DbSet<TRoot> and reference complex members through the root.\nIQueryable<Root> query = ctx.Set<Root>(); // entity shaper guaranteed\nawait query.ExecuteUpdateAsync(s => s.SetProperty(r => r.Address.City, \"x\"));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always root ExecuteUpdate at a DbSet<TEntity> rather than a Select of a complex property.","Reference complex-type members through the owning entity in the SetProperty lambda.","Add an integration test asserting ExecuteUpdate works after switching owned -> complex types."],"tags":["efcore","executeupdate","complex-types","query-translation"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}