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

Code before:
            for (; i > 1; i--)
            {
                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)
    {
        var member = property.GetMemberInfo(forMaterialization, forSet) ?? throw new InvalidOperationException(
                DesignStrings.CompiledModelBackingFieldNotFound(property.DeclaringType.ShortName(), property.Name));

        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;
                }

                member = methodInfo;

                break;

Review comment (bug):
`property.GetMemberInfo(...)` can return `null` for collection navigations/properties (see `PropertyBaseExtensions.TryGetMemberInfo`: it returns `true` with `memberInfo == null` when `IsCollection` is true and no setter/field exists). Throwing `CompiledModelBackingFieldNotFound` on `null` here will make NativeAOT compiled-model generation fail for collection members that EF otherwise treats as valid (no setter/field needed), instead of simply skipping generation of that particular accessor. Consider using `TryGetMemberInfo(...)` directly and: (1) if it returns `false`, throw an `InvalidOperationException` with an appropriate DesignStrings message; (2) if it returns `true` but `memberInfo` is `null`, return `null` from `RegisterPrivateAccessor` (i.e. don’t attempt to create an unsafe accessor for that direction).
```suggestion
        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;
        }
```

Code after:
            for (; i > 1; i--)
            {
                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)
                {