Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/EFCore/ChangeTracking/Internal/ChangeDetector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ public class ChangeDetector : IChangeDetector
private static readonly bool UseOldBehavior37387 =
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue37387", out var enabled) && enabled;

private static readonly bool UseOldBehavior37890 =
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue37890", out var enabled) && enabled;

/// <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
Expand Down Expand Up @@ -339,9 +342,9 @@ public virtual bool DetectComplexPropertyChange(InternalEntryBase entry, IComple

if ((currentValue is null) != (originalValue is null))
{
// If it changed from null to non-null, mark all inner properties as modified
// If it changed from null to non-null or from non-null to null, mark all inner properties as modified
// to ensure the entity is detected as modified and the complex type properties are persisted
if (currentValue is not null)
if (!UseOldBehavior37890 || currentValue is not null)
{
foreach (var innerProperty in complexProperty.ComplexType.GetFlattenedProperties())
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ public override Task Can_save_default_values_in_optional_complex_property_with_m
// See https://github.com/dotnet/efcore/issues/31464
=> Task.CompletedTask;

public override Task Can_null_complex_property_with_default_values_and_multiple_properties(bool async)
// InMemory provider has issues with complex type query compilation and materialization
// See https://github.com/dotnet/efcore/issues/31464
=> Task.CompletedTask;

// Complex type collections are not supported in InMemory provider
// See https://github.com/dotnet/efcore/issues/31464
public override Task Can_change_state_from_Deleted_with_complex_collection(EntityState newState, bool async)
Expand Down
50 changes: 50 additions & 0 deletions test/EFCore.Specification.Tests/ComplexTypesTrackingTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4619,6 +4619,56 @@ await ExecuteWithStrategyInTransactionAsync(
});
}

[ConditionalTheory]
[InlineData(false)]
[InlineData(true)]
public virtual async Task Can_null_complex_property_with_default_values_and_multiple_properties(bool async)
{
await ExecuteWithStrategyInTransactionAsync(
async context =>
{
var entity = Fixture.UseProxies
? context.CreateProxy<EntityWithOptionalMultiPropComplex>()
: new EntityWithOptionalMultiPropComplex();

entity.Id = Guid.NewGuid();
// Set the complex property with default values
entity.ComplexProp = new MultiPropComplex
{
IntValue = 0,
BoolValue = false,
DateValue = default,
};

_ = async ? await context.AddAsync(entity) : context.Add(entity);
_ = async ? await context.SaveChangesAsync() : context.SaveChanges();

Assert.NotNull(entity.ComplexProp);
},
async context =>
{
var entity = async
? await context.Set<EntityWithOptionalMultiPropComplex>().SingleAsync()
: context.Set<EntityWithOptionalMultiPropComplex>().Single();

Assert.NotNull(entity.ComplexProp);

entity.ComplexProp = null;

_ = async ? await context.SaveChangesAsync() : context.SaveChanges();

Assert.Null(entity.ComplexProp);
},
async context =>
{
var entity = async
? await context.Set<EntityWithOptionalMultiPropComplex>().SingleAsync()
: context.Set<EntityWithOptionalMultiPropComplex>().Single();

Assert.Null(entity.ComplexProp);
});
}

public class EntityWithOptionalMultiPropComplex
{
public virtual Guid Id { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,10 @@ public override void Can_write_original_values_for_properties_of_complex_propert
public override Task Can_save_default_values_in_optional_complex_property_with_multiple_properties(bool async)
=> Task.CompletedTask;

// Issue #36175: Complex types with notification change tracking are not supported
public override Task Can_null_complex_property_with_default_values_and_multiple_properties(bool async)
=> Task.CompletedTask;

// Fields can't be proxied
public override Task Can_change_state_from_Deleted_with_complex_field_collection(EntityState newState, bool async)
=> Task.CompletedTask;
Expand Down
Loading