Repository: dotnet/efcore
File: src/EFCore/ChangeTracking/Internal/EntryPropertyValues.cs (C#)

Code before:
    ///     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>
    public override PropertyValues Clone()
    {
        var values = new object?[Properties.Count];
        for (var i = 0; i < values.Length; i++)
        {
            values[i] = GetValueInternal(InternalEntry, Properties[i]);
        }

        bool[]? flags = null;
        var nullableComplexProperties = NullableComplexProperties;
        if (nullableComplexProperties != null && nullableComplexProperties.Count > 0)
        {
            flags = new bool[nullableComplexProperties.Count];
            
            // Track which complex types are null to avoid marking nested properties as null
            var nullComplexTypes = new HashSet<IComplexType>();
            
            for (var i = 0; i < nullableComplexProperties.Count; i++)
            {
                var complexProperty = nullableComplexProperties[i];
                
                // Skip if this property is nested within a complex type that's already null
                if (IsNestedInNullComplexType(complexProperty, nullComplexTypes))
                {
                    continue;
                }
                
                var isNull = GetValueInternal(InternalEntry, complexProperty) == null;
                flags[i] = isNull;
                
                if (isNull)
                {
                    nullComplexTypes.Add(complexProperty.ComplexType);
                }
            }
        }

        var cloned = new ArrayPropertyValues(InternalEntry, values, flags);

        foreach (var complexProperty in ComplexCollectionProperties)
        {
            var collection = (IList?)GetValueInternal(InternalEntry, complexProperty);
            if (collection != null)
            {
                cloned[complexProperty] = collection;
            }
        }


Review comment (suggestion):
@copilot Instead of tracking which properties were null just check whether the value of the containing property (if any) is null

Code after:
    ///     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>
    public override PropertyValues Clone()
    {
        var values = new object?[Properties.Count];
        for (var i = 0; i < values.Length; i++)
        {
            values[i] = GetValueInternal(InternalEntry, Properties[i]);
        }

        bool[]? flags = null;
        var nullableComplexProperties = NullableComplexProperties;
        if (nullableComplexProperties != null && nullableComplexProperties.Count > 0)
        {
            flags = new bool[nullableComplexProperties.Count];
            for (var i = 0; i < nullableComplexProperties.Count; i++)
            {
                flags[i] = GetValueInternal(InternalEntry, nullableComplexProperties[i]) == null;
            }
        }

        var cloned = new ArrayPropertyValues(InternalEntry, values, flags);

        foreach (var complexProperty in ComplexCollectionProperties)
        {
            var collection = (IList?)GetValueInternal(InternalEntry, complexProperty);
            if (collection != null)
            {
                cloned[complexProperty] = collection;
            }
        }

        return cloned;
    }

    /// <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>
    public override void SetValues(PropertyValues propertyValues)
    {
        Check.NotNull(propertyValues);

        var nullableComplexProperties = NullableComplexProperties;
        HashSet<IComplexProperty>? nullComplexProperties = null;
        if (nullableComplexProperties != null)
        {
            for (var i = 0; i < nullableComplexProperties.Count; i++)