@@ -674,6 +674,51 @@ public void GetEntry_throws_when_accessing_invalid_current_ordinal()
674674 Assert . Equal ( CoreStrings . ComplexCollectionEntryOrdinalInvalid ( 5 , "Blog" , "Tags" , 1 ) , ex . Message ) ;
675675 }
676676
677+ [ ConditionalFact ]
678+ public void DetectChanges_detects_changes_in_nested_complex_collections ( )
679+ {
680+ var model = CreateModelWithNestedComplexCollections ( ) ;
681+ var entityType = model . FindEntityType ( typeof ( BlogWithNested ) ) ! ;
682+
683+ var serviceProvider = InMemoryTestHelpers . Instance . CreateContextServices ( model ) ;
684+ var stateManager = serviceProvider . GetRequiredService < IStateManager > ( ) ;
685+ var changeDetector = serviceProvider . GetRequiredService < IChangeDetector > ( ) ;
686+
687+ var blog = new BlogWithNested
688+ {
689+ NestedJson = new NestedJson
690+ {
691+ Item = new NestedItem { Name = "foo" } ,
692+ Items =
693+ [
694+ new NestedItem { Name = "bar" } ,
695+ new NestedItem { Name = "baz" }
696+ ]
697+ }
698+ } ;
699+
700+ var entityEntry = stateManager . GetOrCreateEntry ( blog ) ;
701+ entityEntry . SetEntityState ( EntityState . Unchanged ) ;
702+
703+ Assert . Equal ( EntityState . Unchanged , entityEntry . EntityState ) ;
704+
705+ // Replace the NestedJson with a new instance that has a modified Items collection
706+ blog . NestedJson = blog . NestedJson with
707+ {
708+ Items =
709+ [
710+ new NestedItem { Name = "bar" } ,
711+ new NestedItem { Name = "baz" } ,
712+ new NestedItem { Name = "new-bar" }
713+ ]
714+ } ;
715+
716+ // DetectChanges should detect the change in the nested complex collection
717+ changeDetector . DetectChanges ( stateManager ) ;
718+
719+ Assert . Equal ( EntityState . Modified , entityEntry . EntityState ) ;
720+ }
721+
677722 private static IModel CreateModel ( )
678723 {
679724 var modelBuilder = InMemoryTestHelpers . Instance . CreateConventionBuilder ( ) ;
@@ -688,6 +733,22 @@ private static IModel CreateModel()
688733 return modelBuilder . FinalizeModel ( ) ;
689734 }
690735
736+ private static IModel CreateModelWithNestedComplexCollections ( )
737+ {
738+ var modelBuilder = InMemoryTestHelpers . Instance . CreateConventionBuilder ( ) ;
739+
740+ modelBuilder . Entity < BlogWithNested > ( eb =>
741+ {
742+ eb . ComplexProperty ( e => e . NestedJson , b =>
743+ {
744+ b . ComplexProperty ( a => a . Item ) ;
745+ b . ComplexCollection ( a => a . Items ) ;
746+ } ) ;
747+ } ) ;
748+
749+ return modelBuilder . FinalizeModel ( ) ;
750+ }
751+
691752 private class Blog
692753 {
693754 public int Id { get ; set ; }
@@ -714,4 +775,22 @@ private class Category
714775 public string Name { get ; set ; } = "" ;
715776 public string Description { get ; set ; } = "" ;
716777 }
778+
779+ private class BlogWithNested
780+ {
781+ public int Id { get ; set ; }
782+ public string Name { get ; set ; } = "" ;
783+ public NestedJson NestedJson { get ; set ; } = new ( ) ;
784+ }
785+
786+ private record NestedJson
787+ {
788+ public NestedItem Item { get ; init ; } = new ( ) ;
789+ public List < NestedItem > Items { get ; init ; } = [ ] ;
790+ }
791+
792+ private record NestedItem
793+ {
794+ public string Name { get ; init ; } = "" ;
795+ }
717796}
0 commit comments