{"record":{"id":"24d4b62a7f04c16d","repo":"dotnet/efcore","slug":"executeoperationonownedjsonisnotsupported-24d4b6","errorCode":"ExecuteOperationOnOwnedJsonIsNotSupported","errorMessage":"'{operation}' used over owned type '{entityType}' which is mapped to JSON; '{operation}' on JSON-mapped owned entities is not supported. Consider mapping your type as a complex type instead.","messagePattern":"'(.+?)' used over owned type '(.+?)' which is mapped to JSON; '(.+?)' on JSON-mapped owned entities is not supported\\. Consider mapping your type as a complex type instead\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs","lineNumber":319,"sourceCode":"                    {\n                        if (IsMemberAccess(expression, QueryCompilationContext.Model, out var baseExpression, out var member)\n                            && _sqlTranslator.TryBindMember(\n                                _sqlTranslator.Visit(baseExpression), member, out var target, out var targetProperty))\n                        {\n                            translation = target;\n                            property = targetProperty;\n                            return true;\n                        }\n\n                        translation = null;\n                        property = null;\n                        return false;\n                    }\n            }\n\n            if (targetProperty.DeclaringType is IEntityType entityType && entityType.IsMappedToJson())\n            {\n                throw new InvalidOperationException(\n                    RelationalStrings.ExecuteOperationOnOwnedJsonIsNotSupported(\"ExecuteUpdate\", entityType.DisplayName()));\n            }\n\n            // Hack: when returning a StructuralTypeShaperExpression, _sqlTranslator returns it wrapped by a\n            // StructuralTypeReferenceExpression, which is supposed to be a private wrapper only with the SQL translator.\n            // Call TranslateProjection to unwrap it (need to look into getting rid StructuralTypeReferenceExpression altogether).\n            if (target is not CollectionResultExpression)\n            {\n                target = _sqlTranslator.TranslateProjection(target) is { } unwrappedTarget\n                    ? unwrappedTarget\n                    : throw new InvalidOperationException(RelationalStrings.InvalidPropertyInSetProperty(propertySelector.Print()));\n            }\n\n            switch (target)\n            {\n                case ColumnExpression column:\n                {\n                    Check.DebugAssert(column.TypeMapping is not null);","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs#L301-L337","documentation":"After translating the property selector (line 317-321), EF checks whether the declaring entity type is an owned type mapped to JSON (IsMappedToJson). Bulk updates against an owned JSON entity are not translatable because they would require partial JSON document rewriting that EF does not support for owned entities; the error directs you to model the type as a complex type instead, which is the supported path for column-scoped bulk updates.","triggerScenarios":"SetProperty targeting a scalar property whose declaring type is an owned entity configured with ToJson (e.g. OwnsOne(x => x.Details, builder => builder.ToJson())). E.g. SetProperty(e => e.Details.Notes, \"x\") where Details is a JSON-owned owned entity.","commonSituations":"Migrating from owned-entity table-splitting to JSON mapping and re-running existing ExecuteUpdate calls; attempting to patch a single field inside a JSON-owned entity via ExecuteUpdate; using OwnsOne/OwnsMany + ToJson and trying bulk updates that worked before the JSON switch.","solutions":["Remodel the JSON-mapped owned type as a complex type (ComplexProperty/OwnsOne replaced by ComplexProperty with complex type), which supports ExecuteUpdate via flattened columns or JSON complex-type updates.","If JSON mapping is required, do not bulk-update fields inside it; load the entities, mutate, and call SaveChanges.","Update the entire owning row's JSON column via raw SQL if a partial JSON patch is truly needed."],"exampleFix":"// before (Details is OwnsOne(...).ToJson())\ndb.Orders.ExecuteUpdate(s => s.SetProperty(\n    o => o.Details.Notes, \"shipped\"));\n\n// after (remodel Details as a complex type so columns are updatable)\nmodelBuilder.Entity<Order>()\n    .ComplexProperty(o => o.Details);\n// then ExecuteUpdate works on the flattened column\ndb.Orders.ExecuteUpdate(s => s.SetProperty(\n    o => o.Details.Notes, \"shipped\"));","handlingStrategy":"validation","validationCode":"// Inspect the model: is the target's declaring type a JSON-owned entity?\nvar prop = entityType.GetProperties().First(p => p.Name == \"Notes\");\nvar declaring = prop.DeclaringType as IEntityType;\nbool jsonOwned = declaring is not null && declaring.IsMappedToJson();\nif (jsonOwned) throw new InvalidOperationException(\"Remodel as a complex type before ExecuteUpdate.\");","typeGuard":null,"tryCatchPattern":"try { await q.ExecuteUpdateAsync(s => s.SetProperty(e => e.Details.Notes, v)); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"mapped to JSON\"))\n{ /* switch the owned JSON type to a complex type, or use SaveChanges */ }","preventionTips":["Prefer complex types over JSON-mapped owned entities for data that needs bulk updates.","Keep a single modeling style (complex vs owned-JSON) per updatable aggregate.","Document which aggregates are bulk-updatable so contributors do not target JSON-owned fields."],"tags":["efcore","executeupdate","json","owned-entity","complex-type"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}