{"record":{"id":"f90f3477f97844ba","repo":"dotnet/efcore","slug":"executeupdateoverjsonisnotsupported","errorCode":"ExecuteUpdateOverJsonIsNotSupported","errorMessage":"'ExecuteUpdate' is being used over type '{structuralType}' which is mapped to JSON; 'ExecuteUpdate' on JSON is not supported.","messagePattern":"'ExecuteUpdate' is being used over type '(.+?)' which is mapped to JSON; 'ExecuteUpdate' on JSON is not supported\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs","lineNumber":361,"sourceCode":"                    translatedSetters.Add(new ColumnValueSetter(column, translatedValue));\n                    break;\n                }\n\n                // A table-split complex type is being assigned a new value.\n                // Generate setters for each of the columns mapped to the comlex type.\n                case StructuralTypeShaperExpression\n                {\n                    StructuralType: IComplexType complexType,\n                    ValueBufferExpression: StructuralTypeProjectionExpression\n                } shaper:\n                {\n                    Check.DebugAssert(\n                        targetProperty is IComplexProperty complexProperty && complexProperty.ComplexType == complexType,\n                        \"PropertyBase should be a complex property referring to the correct complex type\");\n\n                    if (complexType.IsMappedToJson())\n                    {\n                        throw new InvalidOperationException(\n                            RelationalStrings.ExecuteUpdateOverJsonIsNotSupported(complexType.DisplayName()));\n                    }\n\n                    var translatedValue = TranslateSetterValueSelector(source, valueSelector, shaper.Type);\n                    ProcessComplexType(shaper, translatedValue);\n\n                    break;\n                }\n\n                case JsonScalarExpression { Json: ColumnExpression jsonColumn } jsonScalar:\n                {\n                    var typeMapping = jsonScalar.TypeMapping;\n                    Check.DebugAssert(typeMapping is not null);\n\n                    // We should never see a JsonScalarExpression without a path - that means we're mapping a JSON scalar directly to a relational column.\n                    // This is in theory possible (e.g. map a DateTime to a 'json' column with a single string timestamp representation inside, instead of to\n                    // SQL Server datetime2), but contrived and unsupported.\n                    Check.DebugAssert(jsonScalar.Path.Count > 0);","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs#L343-L379","documentation":"In the StructuralTypeShaperExpression case for complex types (line 349-369), if the target complex type itself IsMappedToJson, ExecuteUpdate cannot produce a meaningful update for it and throws ExecuteUpdateOverJsonIsNotSupported. JSON-mapped complex types are not writable through ExecuteUpdate at the whole-type level.","triggerScenarios":"SetProperty assigning an entire JSON-mapped complex type value, e.g. SetProperty(e => e.JsonComplexProperty, new MyComplexType { ... }) where the complex property is configured to live inside a JSON column.","commonSituations":"Using ComplexProperty(...).ToJson() (JSON-mapped complex type) and attempting a whole-value ExecuteUpdate on it; mixing table-split complex types with JSON complex types and reusing the same update code for both.","solutions":["If the complex type must be updatable via ExecuteUpdate, map it as a table-split complex type (flattened columns) instead of JSON.","Update individual scalar columns instead of the whole complex value.","Fall back to load + mutate + SaveChanges for JSON complex types."],"exampleFix":"// before (Address is ComplexProperty(...).ToJson())\ndb.Contacts.ExecuteUpdate(s => s.SetProperty(\n    c => c.Address, new Address { City = \"NYC\" }));\n\n// after (map Address as flattened complex columns, not JSON)\nmodelBuilder.Entity<Contact>().ComplexProperty(c => c.Address);\ndb.Contacts.ExecuteUpdate(s => s.SetProperty(\n    c => c.Address.City, \"NYC\"));","handlingStrategy":"validation","validationCode":"// Check whether the target complex type is JSON-mapped before assigning it whole.\nvar cp = entityType.GetComplexProperties().FirstOrDefault(p => p.Name == \"Address\");\nbool jsonComplex = cp?.ComplexType.IsMappedToJson() == true;\nif (jsonComplex) throw new InvalidOperationException(\"Use flattened complex type or update scalars.\");","typeGuard":null,"tryCatchPattern":"try { await q.ExecuteUpdateAsync(s => s.SetProperty(e => e.Address, value)); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"mapped to JSON\"))\n{ /* remap as flattened complex type or update scalar sub-properties */ }","preventionTips":["Map updatable complex types as flattened columns, not JSON.","Update scalar sub-properties rather than whole JSON complex values.","Standardize on one mapping mode per aggregate root."],"tags":["efcore","executeupdate","json","complex-type"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}