{"record":{"id":"44dab5ee8221ecba","repo":"dotnet/efcore","slug":"executeupdate-over-json-columns-is-not-supported-w","errorCode":null,"errorMessage":"ExecuteUpdate over JSON columns is not supported when the column is mapped as an owned entity. Map the column as a complex type instead.","messagePattern":"ExecuteUpdate over JSON columns is not supported when the column is mapped as an owned entity\\. Map the column as a complex type instead\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs","lineNumber":669,"sourceCode":"                            StructuralTypeShaperExpression\n                            {\n                                StructuralType: IComplexType,\n                                ValueBufferExpression: StructuralTypeProjectionExpression projection\n                            }\n                                => projection.BindComplexProperty(complexProperty),\n\n                            _ => throw new UnreachableException()\n                        };\n                }\n            }\n\n            void ProcessStructuralJsonSetter(JsonQueryExpression jsonQuery)\n            {\n                var jsonColumn = jsonQuery.JsonColumn;\n\n                if (jsonQuery.StructuralType is not IComplexType complexType)\n                {\n                    throw new InvalidOperationException(RelationalStrings.JsonExecuteUpdateNotSupportedWithOwnedEntities);\n                }\n\n                Check.DebugAssert(jsonColumn.TypeMapping is not null);\n\n                ProcessColumn(jsonColumn, targetProperty);\n\n                var translatedValue = TranslateSetterValueSelector(source, valueSelector, jsonQuery.Type);\n\n                SqlExpression? serializedValue;\n\n                switch (translatedValue)\n                {\n                    // When an object is instantiated inline (e.g. SetProperty(c => c.ShippingAddress, c => new Address { ... })), we get a SqlConstantExpression\n                    // with the .NET instance. Serialize it to JSON and replace the constant (note that the type mapping is inferred from the\n                    // JSON column on other side - important for e.g. nvarchar vs. json columns)\n                    case SqlConstantExpression { Value: var value }:\n                        serializedValue = new SqlConstantExpression(\n                            RelationalJsonUtilities.SerializeComplexTypeToJson(complexType, value, jsonQuery.IsCollection),","sourceCodeStart":651,"sourceCodeEnd":687,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs#L651-L687","documentation":"Thrown by ProcessStructuralJsonSetter when the JsonQueryExpression's StructuralType is not an IComplexType — i.e. the JSON column is mapped as an owned entity rather than a complex type. ExecuteUpdate over JSON columns only supports the complex-type mapping; owned-entity JSON columns are rejected.","triggerScenarios":"OwnsOne/OwnsMany with ToJson on an entity, then ExecuteUpdate that reaches ProcessStructuralJsonSetter (whole-JSON-object setter path). The structural type resolved is the owned entity type, not a complex type, so the check `is not IComplexType` fires.","commonSituations":"Pre-complex-type owned-JSON models attempting bulk updates; mixing OwnsOne-ToJson with ExecuteUpdate on the whole JSON object.","solutions":["Map the JSON column as a complex type (ComplexProperty) instead of an owned entity.","For owned-entity JSON, fall back to load-modify-SaveChanges.","Split the JSON-owned entity into scalar properties you can set individually if they must be columns."],"exampleFix":"// before\nmodelBuilder.Entity<Root>().OwnsOne(r => r.Info, o => o.ToJson(\"info\"));\nawait ctx.Set<Root>().ExecuteUpdateAsync(s => s.SetProperty(r => r.Info, someValue));\n// after\nmodelBuilder.Entity<Root>().ComplexProperty(r => r.Info);\nawait ctx.Set<Root>().ExecuteUpdateAsync(s => s.SetProperty(r => r.Info, someValue));","handlingStrategy":"validation","validationCode":"// Flag JSON columns mapped as owned entities (instead of complex types).\nforeach (var et in ctx.Model.GetEntityTypes())\nforeach (var nav in et.GetNavigations().Where(n => n.TargetEntityType.IsMappedToJson()))\n    logger.LogWarning(\"JSON column for {Nav} is owned; map as complex type for ExecuteUpdate.\", nav.Name);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Map JSON columns as complex types when whole-object bulk update is needed.","Migrate owned-JSON to complex-JSON where possible.","Use SaveChanges for owned-JSON updates."],"tags":["efcore","executeupdate","owned-json","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"}