{"record":{"id":"576b807b0d95fc8a","repo":"dotnet/efcore","slug":"operation-used-over-owned-type-entitytype","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.ExecuteDelete.cs","lineNumber":22,"sourceCode":"using Microsoft.EntityFrameworkCore.Query.SqlExpressions;\n\nnamespace Microsoft.EntityFrameworkCore.Query;\n\npublic partial class RelationalQueryableMethodTranslatingExpressionVisitor\n{\n    /// <inheritdoc />\n    protected override DeleteExpression TranslateExecuteDelete(ShapedQueryExpression source)\n    {\n        source = source.UpdateShaperExpression(new IncludePruner().Visit(source.ShaperExpression));\n\n        if (source.ShaperExpression is not StructuralTypeShaperExpression { StructuralType: IEntityType entityType } shaper)\n        {\n            throw new InvalidOperationException(RelationalStrings.ExecuteDeleteOnNonEntityType);\n        }\n\n        if (entityType.IsMappedToJson())\n        {\n            throw new InvalidOperationException(\n                RelationalStrings.ExecuteOperationOnOwnedJsonIsNotSupported(\"ExecuteDelete\", entityType.DisplayName()));\n        }\n\n        switch (entityType.GetMappingStrategy())\n        {\n            case RelationalAnnotationNames.TptMappingStrategy:\n                throw new InvalidOperationException(\n                    RelationalStrings.ExecuteOperationOnTPT(\n                        nameof(EntityFrameworkQueryableExtensions.ExecuteDelete),\n                        entityType.DisplayName()));\n\n            // Note that we do allow TPC if the target is a leaf type\n            case RelationalAnnotationNames.TpcMappingStrategy when entityType.GetDirectlyDerivedTypes().Any():\n                throw new InvalidOperationException(\n                    RelationalStrings.ExecuteOperationOnTPC(\n                        nameof(EntityFrameworkQueryableExtensions.ExecuteDelete),\n                        entityType.DisplayName()));\n        }","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteDelete.cs#L4-L40","documentation":"TranslateExecuteDelete checks entityType.IsMappedToJson() and refuses to delete JSON-mapped owned entities. JSON-mapped owned data lives as a JSON document inside the owner's column; deleting it independently of the owner is not a meaningful server operation in EF's model. The message suggests complex types as an alternative mapping.","triggerScenarios":"context.Owners.SelectMany(o => o.JsonCollection).ExecuteDelete() where JsonCollection is an OwnsMany(...).ToJson() navigation; calling ExecuteDelete on a query rooted at a JSON-mapped owned entity; targeting an owned entity mapped via .ToJson().","commonSituations":"Treating a JSON collection as a regular related entity and attempting bulk delete; refactoring from table-splitting to JSON mapping and reusing an existing ExecuteDelete call.","solutions":["Delete the owner entity (which removes its JSON document), or update the owner to null/remove the element from the collection via SaveChanges.","If independent deletes are required, remap the owned type to its own table (ToTable) or use a complex type instead of .ToJson().","Use raw SQL to mutate the JSON document if a partial JSON delete is needed (database-specific JSON functions)."],"exampleFix":"// before (delete JSON-mapped owned)\nawait db.Owners\n    .SelectMany(o => o.Tags /* OwnsMany().ToJson() */)\n    .ExecuteDeleteAsync();\n// after (delete owner, or remap owned to a table)\nawait db.Owners.Where(o => o.Id == id).ExecuteDeleteAsync();","handlingStrategy":"validation","validationCode":"// Block ExecuteDelete on JSON-mapped owned entities up front.\nvar et = db.Model.FindEntityType(typeof(TEntity))!;\nif (et.IsMappedToJson())\n    throw new InvalidOperationException(\n        $\"{et.Name} is JSON-mapped; delete the owner or remap to a table/complex type.\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Delete the owner entity for JSON-mapped owned data.","Use OwnsMany(...).ToJson() only for read-heavy data you never bulk-delete independently.","Consider complex types for owned data that needs simpler lifecycle."],"tags":["efcore","executedelete","json","owned-types","mapping"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}