Repository: dotnet/efcore
File: src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs (C#)

Code before:
                if (accessors[i - 1].Item1 != null)
                {
                    break;
                }
            }

            property.AddRuntimeAnnotation(CoreAnnotationNames.UnsafeAccessors, accessors.Take(i).ToArray());
        }

        return memberAccessReplacements;
    }

    private QualifiedName? RegisterPrivateAccessor(
        IPropertyBase property,
        bool forMaterialization,
        bool forSet,
        string @namespace,
        BidirectionalDictionary<Type, string> unsafeAccessorClassNames,
        Dictionary<Type, HashSet<MemberInfo>> unsafeAccessorTypes,
        ref Dictionary<MemberInfo, QualifiedName>? memberAccessReplacements)
    {
        MemberInfo? member;
        if (!property.TryGetMemberInfo(forMaterialization, forSet, out member, out _))
        {
            throw new InvalidOperationException(
                DesignStrings.CompiledModelBackingFieldNotFound(property.DeclaringType.ShortName(), property.Name));
        }

        if (member == null)
        {
            return null;
        }
        switch (member)
        {
            case FieldInfo field:
            {
                if (field.IsPublic
                    || (memberAccessReplacements?.ContainsKey(field)) == true)
                {
                    return null;
                }

                break;
            }
            case PropertyInfo propertyInfo:
            {
                var methodInfo = forSet ? propertyInfo.SetMethod! : propertyInfo.GetMethod!;
                if (methodInfo.IsPublic
                    || methodInfo.IsStatic
                    || (memberAccessReplacements?.ContainsKey(methodInfo)) == true)
                {

Review comment (bug):
`TryGetMemberInfo` can fail for reasons other than “backing field cannot be inferred” (e.g. missing getter/setter depending on the configured `PropertyAccessMode`). The current code ignores the `errorMessage` out-parameter and always throws `CompiledModelBackingFieldNotFound`, which can be misleading. Consider capturing `errorMessage` and either throwing it as-is, or only using `CompiledModelBackingFieldNotFound` for the specific “no backing field” cases (and otherwise throwing the returned `errorMessage`).
```suggestion
        if (!property.TryGetMemberInfo(forMaterialization, forSet, out member, out var errorMessage))
        {
            throw new InvalidOperationException(
                errorMessage
                ?? DesignStrings.CompiledModelBackingFieldNotFound(property.DeclaringType.ShortName(), property.Name));
```

Code after:
                if (accessors[i - 1].Item1 != null)
                {
                    break;
                }
            }

            property.AddRuntimeAnnotation(CoreAnnotationNames.UnsafeAccessors, accessors.Take(i).ToArray());
        }

        return memberAccessReplacements;
    }

    private QualifiedName? RegisterPrivateAccessor(
        IPropertyBase property,
        bool forMaterialization,
        bool forSet,
        string @namespace,
        BidirectionalDictionary<Type, string> unsafeAccessorClassNames,
        Dictionary<Type, HashSet<MemberInfo>> unsafeAccessorTypes,
        ref Dictionary<MemberInfo, QualifiedName>? memberAccessReplacements)
    {
        if (!property.TryGetMemberInfo(forMaterialization, forSet, out var member, out var error))
        {
            throw new InvalidOperationException(error);
        }

        if (member == null)
        {
            return null;
        }
        switch (member)
        {
            case FieldInfo field:
            {
                if (field.IsPublic
                    || (memberAccessReplacements?.ContainsKey(field)) == true)
                {
                    return null;
                }

                break;
            }
            case PropertyInfo propertyInfo:
            {
                var methodInfo = forSet ? propertyInfo.SetMethod! : propertyInfo.GetMethod!;
                if (methodInfo.IsPublic
                    || methodInfo.IsStatic
                    || (memberAccessReplacements?.ContainsKey(methodInfo)) == true)
                {
                    return null;
                }