dotnet/efcore · error · NotImplementedException

Private static field access

Error message

Private static field access

What it means

Thrown by LinqToCSharpSyntaxTranslator.TranslateNonPublicMemberAccess when a MemberExpression for a non-public member has a null Expression — i.e. the member is being accessed statically (memberExpression.Expression is null). The [UnsafeAccessor]-based pattern only handles instance access; private static field/property read is not implemented.

Solutions

  1. Avoid reading private static fields/properties through expression trees destined for this translator; expose the value via a public static accessor and reference that instead.
  2. If the value is constant, compute it out-of-band and inject it as a ConstantExpression.
  3. Restructure so the access is on an instance rather than static (pass the holder object into the lambda).

Example fix

// before — reads a private static field via reflection-built MemberExpression
var field = typeof(Config).GetField("s_value",
    BindingFlags.NonPublic | BindingFlags.Static)!;
var access = Expression.Field(null, field); // null target => static

// after — expose a public static accessor and reference it
public static int Value => s_value;
var access = Expression.Property(null, nameof(Config.Value));
Defensive patterns

Strategy: validation

Validate before calling

// Reject MemberExpressions that target non-public static members.
using System.Linq.Expressions;
using System.Reflection;

bool TargetsPrivateStaticMember(Expression e)
{
    bool bad = false;
    new MemberChecker(m =>
    {
        if (m.Expression is null && m.Member is not null)
        {
            var accessibility = m.Member switch
            {
                FieldInfo f => f.Attributes,
                PropertyInfo p => p.GetMethod?.Attributes ?? MethodAttributes.Private,
                _ => MethodAttributes.Private,
            };
            if (!accessibility.HasFlag(MethodAttributes.Public)) bad = true;
        }
    }).Visit(e);
    return bad;
}

class MemberChecker(Action<MemberExpression> onMember) : ExpressionVisitor
{
    protected override Expression VisitMember(MemberExpression m) { onMember(m); return base.VisitMember(m); }
}

Prevention

When it happens

Trigger: An expression tree contains a MemberExpression referencing a private/internal static field or a private static property's getter with no object instance, and that member reaches the non-public member access path of the translator.

Common situations: Manually-constructed expression trees that read private static state (singletons, caches) for compiled-query source generation; provider extensions that wrap internal static fields; reflective helpers that surface static private members as MemberExpression.

Related errors


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/7ab816353f46bc3e. Report an issue: GitHub.

Appendix: source

Thrown at src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs:1674

                Result = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, expression, IdentifierName(member.Member.Name));
                break;
        }

        return member;
    }

    /// <summary>
    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
    ///     any release. You should only use it directly in your code with extreme caution and knowing that
    ///     doing so can result in application failures when updating to a new Entity Framework Core release.
    /// </summary>
    protected virtual void TranslateNonPublicMemberAccess(MemberExpression memberExpression)
    {
        if (memberExpression.Expression is null)
        {
            throw new NotImplementedException("Private static field access");
        }

        // Get an unsafe accessor for this field/property (this internally caches and adds it to the output list of unsafe accessors)

        // [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "<Name>k__BackingField")]
        // static extern ref int UnsafeAccessor_Foo_Name(Foo f);
        var unsafeAccessorDeclaration = GetUnsafeAccessorDeclaration(
            memberExpression.Member is PropertyInfo propertyInfo
                ? propertyInfo.GetMethod ?? throw new UnreachableException("Attempting to read from property without getter")
                : memberExpression.Member,
            forWrite: false);

        // The unsafe accessor declaration has been created; invoke it.
        Result =
            _g.InvocationExpression(
                _g.IdentifierName(unsafeAccessorDeclaration.Identifier.Text),
                Translate<ExpressionSyntax>(memberExpression.Expression));
    }

View on GitHub (pinned to 3a2006ef56)