{"record":{"id":"c35755977cede226","repo":"dotnet/efcore","slug":"compound-assignment-of-private-property-not-yet-su","errorCode":null,"errorMessage":"Compound assignment of private property not yet supported","messagePattern":"Compound assignment of private property not yet supported","errorType":"exception","errorClass":"NotImplementedException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs","lineNumber":1736,"sourceCode":"                : memberExpression.Member,\n            forWrite: true);\n\n        // The unsafe accessor declaration has been created; invoke it.\n        Result = memberExpression.Member switch\n        {\n            FieldInfo => AssignmentExpression(\n                assignmentKind,\n                (ExpressionSyntax)_g.InvocationExpression(\n                    _g.IdentifierName(unsafeAccessorDeclaration.Identifier.Text),\n                    Translate<ExpressionSyntax>(memberExpression.Expression)),\n                Translate<ExpressionSyntax>(value)),\n\n            PropertyInfo =>\n                _g.InvocationExpression(\n                    _g.IdentifierName(unsafeAccessorDeclaration.Identifier.Text), Translate<ExpressionSyntax>(memberExpression.Expression),\n                    assignmentKind is SyntaxKind.SimpleAssignmentExpression\n                        ? Translate<ExpressionSyntax>(value)\n                        : throw new NotImplementedException(\"Compound assignment of private property not yet supported\")),\n\n            _ => throw new UnreachableException()\n        };\n    }\n\n    private MethodDeclarationSyntax GetUnsafeAccessorDeclaration(MemberInfo member, bool forWrite = false)\n    {\n        MethodDeclarationSyntax? unsafeAccessorDeclaration;\n\n        switch (member)\n        {\n            case FieldInfo field:\n            {\n                // Note that we generate two accessors for fields (get/set), since the get accessor needs to be used in expression trees,\n                // which don't support ref return\n                if (_fieldUnsafeAccessors.TryGetValue((field, forWrite), out unsafeAccessorDeclaration))\n                {\n                    return unsafeAccessorDeclaration;","sourceCodeStart":1718,"sourceCodeEnd":1754,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs#L1718-L1754","documentation":"For non-public properties the generated [UnsafeAccessor] setter handles only simple assignment. A compound assignment (+=, -=, ...) on a private property would need a read through the get accessor and a write through the set accessor as separate operations, which is not implemented, so TranslateNonPublicMemberAssignment throws NotImplementedException when assignmentKind is not SimpleAssignmentExpression.","triggerScenarios":"A lambda performs a compound assignment on a non-public property, e.g. privateProp += value, where privateProp is a property with non-public accessors reached via the unsafe-accessor path.","commonSituations":"Accumulating into a private/internal property counter inside a compiled expression; using += on a property whose accessors are not public.","solutions":["Expand the compound assignment into an explicit read plus a simple write: privateProp = privateProp + value (simple assignment, value is the sum).","Make the property public so the normal C# compound-assignment path applies.","Perform the accumulation outside the compiled query expression."],"exampleFix":"// before\nx.Counter += n;  // AddAssign on a private property -> throws\n// after\nx.Counter = x.Counter + n;  // simple assignment; read and write each supported","handlingStrategy":"validation","validationCode":"// Flag compound assignment on non-public properties\nprotected override Expression VisitBinary(BinaryExpression b) {\n    if (b.NodeType != ExpressionType.Assign && b.Left is MemberExpression m\n        && m.Member is System.Reflection.PropertyInfo p\n        && !(p.GetMethod?.IsPublic ?? false)) Found = true;\n    return b;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Expand += into an explicit read plus simple write.","Make the property public if compound assignment is needed.","Perform accumulation outside the compiled expression."],"tags":["ef-core","linq","expression-tree","unsafe-accessor","assignment","properties"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}