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
4 changes: 0 additions & 4 deletions NuGet.config
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@
<add key="dotnet10-transport" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet10-transport/nuget/v3/index.json" />
<add key="dotnet-public" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public/nuget/v3/index.json" />
</packageSources>
<auditSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</auditSources>
<disabledPackageSources>
<clear />
<!--Begin: Package sources managed by Dependency Flow automation. Do not edit the sources below.-->
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/ChangeTracking/Internal/ChangeDetector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ private bool LocalDetectChanges(InternalEntryBase entry)
}
}

foreach (var complexProperty in entry.StructuralType.GetComplexProperties())
foreach (var complexProperty in entry.StructuralType.GetFlattenedComplexProperties())
{
if (complexProperty.IsCollection)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,51 @@ public void GetEntry_throws_when_accessing_invalid_current_ordinal()
Assert.Equal(CoreStrings.ComplexCollectionEntryOrdinalInvalid(5, "Blog", "Tags", 1), ex.Message);
}

[ConditionalFact]
public void DetectChanges_detects_changes_in_nested_complex_collections()
{
var model = CreateModelWithNestedComplexCollections();
var entityType = model.FindEntityType(typeof(BlogWithNested))!;

var serviceProvider = InMemoryTestHelpers.Instance.CreateContextServices(model);
var stateManager = serviceProvider.GetRequiredService<IStateManager>();
var changeDetector = serviceProvider.GetRequiredService<IChangeDetector>();

var blog = new BlogWithNested
{
NestedJson = new NestedJson
{
Item = new NestedItem { Name = "foo" },
Items =
[
new NestedItem { Name = "bar" },
new NestedItem { Name = "baz" }
]
}
};

var entityEntry = stateManager.GetOrCreateEntry(blog);
entityEntry.SetEntityState(EntityState.Unchanged);

Assert.Equal(EntityState.Unchanged, entityEntry.EntityState);

// Replace the NestedJson with a new instance that has a modified Items collection
blog.NestedJson = blog.NestedJson with
{
Items =
[
new NestedItem { Name = "bar" },
new NestedItem { Name = "baz" },
new NestedItem { Name = "new-bar" }
]
};

// DetectChanges should detect the change in the nested complex collection
changeDetector.DetectChanges(stateManager);

Assert.Equal(EntityState.Modified, entityEntry.EntityState);
}

private static IModel CreateModel()
{
var modelBuilder = InMemoryTestHelpers.Instance.CreateConventionBuilder();
Expand All @@ -688,6 +733,22 @@ private static IModel CreateModel()
return modelBuilder.FinalizeModel();
}

private static IModel CreateModelWithNestedComplexCollections()
{
var modelBuilder = InMemoryTestHelpers.Instance.CreateConventionBuilder();

modelBuilder.Entity<BlogWithNested>(eb =>
{
eb.ComplexProperty(e => e.NestedJson, b =>
{
b.ComplexProperty(a => a.Item);
b.ComplexCollection(a => a.Items);
});
});

return modelBuilder.FinalizeModel();
}

private class Blog
{
public int Id { get; set; }
Expand All @@ -714,4 +775,22 @@ private class Category
public string Name { get; set; } = "";
public string Description { get; set; } = "";
}

private class BlogWithNested
{
public int Id { get; set; }
public string Name { get; set; } = "";
public NestedJson NestedJson { get; set; } = new();
}

private record NestedJson
{
public NestedItem Item { get; init; } = new();
public List<NestedItem> Items { get; init; } = [];
}

private record NestedItem
{
public string Name { get; init; } = "";
}
}
Loading