{"record":{"id":"884893bdf2264cf9","repo":"dotnet/efcore","slug":"operation-used-over-owned-type-entitytype-884893","errorCode":null,"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/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs#L301-L337","documentation":"Thrown when the property targeted by ExecuteUpdate/SetProperty belongs to an owned entity type that is mapped to JSON. Bulk updates inside JSON-mapped owned entities are not supported by the relational pipeline; the recommendation is to use complex types instead.","triggerScenarios":"Configuring an owned entity with ToJson(...) (e.g. OwnsOne(x => x.RequiredAssociate, o => o.ToJson())) and then calling ExecuteUpdate with a setter that targets a property of that owned entity. The OwnedJsonBulkUpdateRelationalTestBase asserts this for both ExecuteDelete and ExecuteUpdate.","commonSituations":"Porting an owned-JSON model and trying to bulk-update nested objects; mixing JSON-owned entities with ExecuteUpdate after upgrading EF Core.","solutions":["Remodel the JSON-owned entity as a complex type (OwnsComplexType / ComplexProperty) which supports ExecuteUpdate over its scalar members.","Fall back to loading the entities, mutating, and SaveChanges for JSON-owned entities.","Move the property you need to update out of the JSON-owned entity into the owning entity's table."],"exampleFix":"// before\nmodelBuilder.Entity<RootEntity>()\n    .OwnsOne(r => r.RequiredAssociate, o => o.ToJson(\"Associate\"));\nawait ctx.Set<RootEntity>().ExecuteUpdateAsync(s => s.SetProperty(r => r.RequiredAssociate.Name, \"x\"));\n// after\nmodelBuilder.Entity<RootEntity>()\n    .ComplexProperty(r => r.RequiredAssociate);\nawait ctx.Set<RootEntity>().ExecuteUpdateAsync(s => s.SetProperty(r => r.RequiredAssociate.Name, \"x\"));","handlingStrategy":"validation","validationCode":"// Reject JSON-owned entities at config time when ExecuteUpdate is needed.\nforeach (var et in ctx.Model.GetEntityTypes())\nforeach (var nav in et.GetNavigations().Where(n => n.TargetEntityType.IsMappedToJson()))\n{\n    logger.LogWarning(\"{EntityType}.{Nav} is JSON-owned; ExecuteUpdate unsupported.\", et.Name, nav.Name);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer complex types over owned entities for JSON columns when bulk updates are needed.","Centralize ownership configuration so JSON-owned entities are deliberate.","Add a test that asserts ExecuteUpdate is never called against JSON-owned entities."],"tags":["efcore","executeupdate","owned-json","query-translation"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}