@@ -25,6 +25,234 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking
25
25
{
26
26
public class ChangeTrackerTest
27
27
{
28
+ [ ConditionalTheory ]
29
+ [ InlineData ( 0 , 0 ) ]
30
+ [ InlineData ( 1 , 0 ) ]
31
+ [ InlineData ( 0 , 1 ) ]
32
+ [ InlineData ( 1 , 1 ) ]
33
+ public void Can_Add_with_identifying_relationships_dependent_first ( int principalKeyValue , int dependentKeyValue )
34
+ {
35
+ using var context = new EarlyLearningCenter ( ) ;
36
+
37
+ var added1 = context . Add ( new DependentGG { Id = dependentKeyValue , PrincipalGG = new PrincipalGG { Id = principalKeyValue } } ) . Entity ;
38
+ Assert . Equal ( EntityState . Added , context . Entry ( added1 ) . State ) ;
39
+ Assert . Equal ( EntityState . Added , context . Entry ( added1 . PrincipalGG ) . State ) ;
40
+
41
+ var added2 = context . Add ( new DependentNG { Id = dependentKeyValue , PrincipalNG = new PrincipalNG { Id = principalKeyValue } } ) . Entity ;
42
+ Assert . Equal ( EntityState . Added , context . Entry ( added2 ) . State ) ;
43
+ Assert . Equal ( EntityState . Added , context . Entry ( added2 . PrincipalNG ) . State ) ;
44
+
45
+ var added3 = context . Add ( new DependentNN { Id = dependentKeyValue , PrincipalNN = new PrincipalNN { Id = principalKeyValue } } ) . Entity ;
46
+ Assert . Equal ( EntityState . Added , context . Entry ( added3 ) . State ) ;
47
+ Assert . Equal ( EntityState . Added , context . Entry ( added3 . PrincipalNN ) . State ) ;
48
+
49
+ var added4 = context . Add ( new DependentGN { Id = dependentKeyValue , PrincipalGN = new PrincipalGN { Id = principalKeyValue } } ) . Entity ;
50
+ Assert . Equal ( EntityState . Added , context . Entry ( added4 ) . State ) ;
51
+ Assert . Equal ( EntityState . Added , context . Entry ( added4 . PrincipalGN ) . State ) ;
52
+ }
53
+
54
+ [ ConditionalTheory ]
55
+ [ InlineData ( 0 , 0 ) ]
56
+ [ InlineData ( 1 , 0 ) ]
57
+ [ InlineData ( 0 , 1 ) ]
58
+ [ InlineData ( 1 , 1 ) ]
59
+ public void Can_Add_with_identifying_relationships_principal_first ( int principalKeyValue , int dependentKeyValue )
60
+ {
61
+ using var context = new EarlyLearningCenter ( ) ;
62
+
63
+ var added1 = context . Add ( new PrincipalGG { Id = principalKeyValue , DependentGG = new DependentGG { Id = dependentKeyValue } } ) . Entity ;
64
+ Assert . Equal ( EntityState . Added , context . Entry ( added1 ) . State ) ;
65
+ Assert . Equal ( EntityState . Added , context . Entry ( added1 . DependentGG ) . State ) ;
66
+
67
+ var added2 = context . Add ( new PrincipalNG { Id = principalKeyValue , DependentNG = new DependentNG { Id = dependentKeyValue } } ) . Entity ;
68
+ Assert . Equal ( EntityState . Added , context . Entry ( added2 ) . State ) ;
69
+ Assert . Equal ( EntityState . Added , context . Entry ( added2 . DependentNG ) . State ) ;
70
+
71
+ var added3 = context . Add ( new PrincipalNN { Id = principalKeyValue , DependentNN = new DependentNN { Id = dependentKeyValue } } ) . Entity ;
72
+ Assert . Equal ( EntityState . Added , context . Entry ( added3 ) . State ) ;
73
+ Assert . Equal ( EntityState . Added , context . Entry ( added3 . DependentNN ) . State ) ;
74
+
75
+ var added4 = context . Add ( new PrincipalGN { Id = principalKeyValue , DependentGN = new DependentGN { Id = dependentKeyValue } } ) . Entity ;
76
+ Assert . Equal ( EntityState . Added , context . Entry ( added4 ) . State ) ;
77
+ Assert . Equal ( EntityState . Added , context . Entry ( added4 . DependentGN ) . State ) ;
78
+ }
79
+
80
+ [ ConditionalFact ]
81
+ public void Can_Attach_with_identifying_relationships_dependent_first ( )
82
+ {
83
+ using var context = new EarlyLearningCenter ( ) ;
84
+
85
+ var added1 = context . Attach ( new DependentGG { PrincipalGG = new PrincipalGG ( ) } ) . Entity ;
86
+ Assert . Equal ( EntityState . Added , context . Entry ( added1 ) . State ) ;
87
+ Assert . Equal ( EntityState . Added , context . Entry ( added1 . PrincipalGG ) . State ) ;
88
+
89
+ var added2 = context . Attach ( new DependentNG { PrincipalNG = new PrincipalNG ( ) } ) . Entity ;
90
+ Assert . Equal ( EntityState . Added , context . Entry ( added2 ) . State ) ;
91
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added2 . PrincipalNG ) . State ) ;
92
+
93
+ var added3 = context . Attach ( new DependentNN { PrincipalNN = new PrincipalNN ( ) } ) . Entity ;
94
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added3 ) . State ) ;
95
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added3 . PrincipalNN ) . State ) ;
96
+
97
+ var added4 = context . Attach ( new DependentGN { PrincipalGN = new PrincipalGN ( ) } ) . Entity ;
98
+ Assert . Equal ( EntityState . Added , context . Entry ( added4 ) . State ) ;
99
+ Assert . Equal ( EntityState . Added , context . Entry ( added4 . PrincipalGN ) . State ) ;
100
+ }
101
+
102
+ [ ConditionalFact ]
103
+ public void Can_Attach_with_identifying_relationships_dependent_first_with_principal_keys_set ( )
104
+ {
105
+ using var context = new EarlyLearningCenter ( ) ;
106
+
107
+ var added1 = context . Attach ( new DependentGG { PrincipalGG = new PrincipalGG { Id = 1 } } ) . Entity ;
108
+ Assert . Equal ( EntityState . Added , context . Entry ( added1 ) . State ) ;
109
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added1 . PrincipalGG ) . State ) ;
110
+
111
+ var added2 = context . Attach ( new DependentNG { PrincipalNG = new PrincipalNG { Id = 1 } } ) . Entity ;
112
+ Assert . Equal ( EntityState . Added , context . Entry ( added2 ) . State ) ;
113
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added2 . PrincipalNG ) . State ) ;
114
+
115
+ var added3 = context . Attach ( new DependentNN { PrincipalNN = new PrincipalNN { Id = 1 } } ) . Entity ;
116
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added3 ) . State ) ;
117
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added3 . PrincipalNN ) . State ) ;
118
+
119
+ var added4 = context . Attach ( new DependentGN { PrincipalGN = new PrincipalGN { Id = 1 } } ) . Entity ;
120
+ Assert . Equal ( EntityState . Added , context . Entry ( added4 ) . State ) ;
121
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added4 . PrincipalGN ) . State ) ;
122
+ }
123
+
124
+ [ ConditionalFact ]
125
+ public void Can_Attach_with_identifying_relationships_dependent_first_with_dependent_keys_set ( )
126
+ {
127
+ using var context = new EarlyLearningCenter ( ) ;
128
+
129
+ var added1 = context . Attach ( new DependentGG { Id = 1 , PrincipalGG = new PrincipalGG ( ) } ) . Entity ;
130
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added1 ) . State ) ;
131
+ Assert . Equal ( EntityState . Added , context . Entry ( added1 . PrincipalGG ) . State ) ;
132
+
133
+ var added2 = context . Attach ( new DependentNG { Id = 1 , PrincipalNG = new PrincipalNG ( ) } ) . Entity ;
134
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added2 ) . State ) ;
135
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added2 . PrincipalNG ) . State ) ;
136
+
137
+ var added3 = context . Attach ( new DependentNN { Id = 1 , PrincipalNN = new PrincipalNN ( ) } ) . Entity ;
138
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added3 ) . State ) ;
139
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added3 . PrincipalNN ) . State ) ;
140
+
141
+ var added4 = context . Attach ( new DependentGN { Id = 1 , PrincipalGN = new PrincipalGN ( ) } ) . Entity ;
142
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added4 ) . State ) ;
143
+ Assert . Equal ( EntityState . Added , context . Entry ( added4 . PrincipalGN ) . State ) ;
144
+ }
145
+
146
+ [ ConditionalFact ]
147
+ public void Can_Attach_with_identifying_relationships_dependent_first_with_all_keys_set ( )
148
+ {
149
+ using var context = new EarlyLearningCenter ( ) ;
150
+
151
+ var added1 = context . Attach ( new DependentGG { Id = 1 , PrincipalGG = new PrincipalGG { Id = 1 } } ) . Entity ;
152
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added1 ) . State ) ;
153
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added1 . PrincipalGG ) . State ) ;
154
+
155
+ var added2 = context . Attach ( new DependentNG { Id = 1 , PrincipalNG = new PrincipalNG { Id = 1 } } ) . Entity ;
156
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added2 ) . State ) ;
157
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added2 . PrincipalNG ) . State ) ;
158
+
159
+ var added3 = context . Attach ( new DependentNN { Id = 1 , PrincipalNN = new PrincipalNN { Id = 1 } } ) . Entity ;
160
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added3 ) . State ) ;
161
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added3 . PrincipalNN ) . State ) ;
162
+
163
+ var added4 = context . Attach ( new DependentGN { Id = 1 , PrincipalGN = new PrincipalGN { Id = 1 } } ) . Entity ;
164
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added4 ) . State ) ;
165
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added4 . PrincipalGN ) . State ) ;
166
+ }
167
+
168
+ [ ConditionalFact ]
169
+ public void Can_Attach_with_identifying_relationships_principal_first ( )
170
+ {
171
+ using var context = new EarlyLearningCenter ( ) ;
172
+
173
+ var added1 = context . Attach ( new PrincipalGG { DependentGG = new DependentGG ( ) } ) . Entity ;
174
+ Assert . Equal ( EntityState . Added , context . Entry ( added1 ) . State ) ;
175
+ Assert . Equal ( EntityState . Added , context . Entry ( added1 . DependentGG ) . State ) ;
176
+
177
+ var added2 = context . Attach ( new PrincipalNG { DependentNG = new DependentNG ( ) } ) . Entity ;
178
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added2 ) . State ) ;
179
+ Assert . Equal ( EntityState . Added , context . Entry ( added2 . DependentNG ) . State ) ;
180
+
181
+ var added3 = context . Attach ( new PrincipalNN { DependentNN = new DependentNN ( ) } ) . Entity ;
182
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added3 ) . State ) ;
183
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added3 . DependentNN ) . State ) ;
184
+
185
+ var added4 = context . Attach ( new PrincipalGN { DependentGN = new DependentGN ( ) } ) . Entity ;
186
+ Assert . Equal ( EntityState . Added , context . Entry ( added4 ) . State ) ;
187
+ Assert . Equal ( EntityState . Added , context . Entry ( added4 . DependentGN ) . State ) ;
188
+ }
189
+
190
+ [ ConditionalFact ]
191
+ public void Can_Attach_with_identifying_relationships_principal_first_with_principal_keys_set ( )
192
+ {
193
+ using var context = new EarlyLearningCenter ( ) ;
194
+
195
+ var added1 = context . Attach ( new PrincipalGG { Id = 1 , DependentGG = new DependentGG ( ) } ) . Entity ;
196
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added1 ) . State ) ;
197
+ Assert . Equal ( EntityState . Added , context . Entry ( added1 . DependentGG ) . State ) ;
198
+
199
+ var added2 = context . Attach ( new PrincipalNG { Id = 1 , DependentNG = new DependentNG ( ) } ) . Entity ;
200
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added2 ) . State ) ;
201
+ Assert . Equal ( EntityState . Added , context . Entry ( added2 . DependentNG ) . State ) ;
202
+
203
+ var added3 = context . Attach ( new PrincipalNN { Id = 1 , DependentNN = new DependentNN ( ) } ) . Entity ;
204
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added3 ) . State ) ;
205
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added3 . DependentNN ) . State ) ;
206
+
207
+ var added4 = context . Attach ( new PrincipalGN { Id = 1 , DependentGN = new DependentGN ( ) } ) . Entity ;
208
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added4 ) . State ) ;
209
+ Assert . Equal ( EntityState . Added , context . Entry ( added4 . DependentGN ) . State ) ;
210
+ }
211
+
212
+ [ ConditionalFact ]
213
+ public void Can_Attach_with_identifying_relationships_principal_first_with_dependent_keys_set ( )
214
+ {
215
+ using var context = new EarlyLearningCenter ( ) ;
216
+
217
+ var added1 = context . Attach ( new PrincipalGG { DependentGG = new DependentGG { Id = 1 } } ) . Entity ;
218
+ Assert . Equal ( EntityState . Added , context . Entry ( added1 ) . State ) ;
219
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added1 . DependentGG ) . State ) ;
220
+
221
+ var added2 = context . Attach ( new PrincipalNG { DependentNG = new DependentNG { Id = 1 } } ) . Entity ;
222
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added2 ) . State ) ;
223
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added2 . DependentNG ) . State ) ;
224
+
225
+ var added3 = context . Attach ( new PrincipalNN { DependentNN = new DependentNN { Id = 1 } } ) . Entity ;
226
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added3 ) . State ) ;
227
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added3 . DependentNN ) . State ) ;
228
+
229
+ var added4 = context . Attach ( new PrincipalGN { DependentGN = new DependentGN { Id = 1 } } ) . Entity ;
230
+ Assert . Equal ( EntityState . Added , context . Entry ( added4 ) . State ) ;
231
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added4 . DependentGN ) . State ) ;
232
+ }
233
+
234
+ [ ConditionalFact ]
235
+ public void Can_Attach_with_identifying_relationships_principal_first_with_all_keys_set ( )
236
+ {
237
+ using var context = new EarlyLearningCenter ( ) ;
238
+
239
+ var added1 = context . Attach ( new PrincipalGG { Id = 1 , DependentGG = new DependentGG { Id = 1 } } ) . Entity ;
240
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added1 ) . State ) ;
241
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added1 . DependentGG ) . State ) ;
242
+
243
+ var added2 = context . Attach ( new PrincipalNG { Id = 1 , DependentNG = new DependentNG { Id = 1 } } ) . Entity ;
244
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added2 ) . State ) ;
245
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added2 . DependentNG ) . State ) ;
246
+
247
+ var added3 = context . Attach ( new PrincipalNN { Id = 1 , DependentNN = new DependentNN { Id = 1 } } ) . Entity ;
248
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added3 ) . State ) ;
249
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added3 . DependentNN ) . State ) ;
250
+
251
+ var added4 = context . Attach ( new PrincipalGN { Id = 1 , DependentGN = new DependentGN { Id = 1 } } ) . Entity ;
252
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added4 ) . State ) ;
253
+ Assert . Equal ( EntityState . Unchanged , context . Entry ( added4 . DependentGN ) . State ) ;
254
+ }
255
+
28
256
[ ConditionalFact ]
29
257
public void Change_tracker_can_be_cleared ( )
30
258
{
@@ -2529,6 +2757,54 @@ private class WhoAmI
2529
2757
public string ToDisagree { get ; set ; }
2530
2758
}
2531
2759
2760
+ private class PrincipalGG
2761
+ {
2762
+ public int Id { get ; set ; }
2763
+ public DependentGG DependentGG { get ; set ; }
2764
+ }
2765
+
2766
+ private class DependentGG
2767
+ {
2768
+ public int Id { get ; set ; }
2769
+ public PrincipalGG PrincipalGG { get ; set ; }
2770
+ }
2771
+
2772
+ private class PrincipalNN
2773
+ {
2774
+ public int Id { get ; set ; }
2775
+ public DependentNN DependentNN { get ; set ; }
2776
+ }
2777
+
2778
+ private class DependentNN
2779
+ {
2780
+ public int Id { get ; set ; }
2781
+ public PrincipalNN PrincipalNN { get ; set ; }
2782
+ }
2783
+
2784
+ private class PrincipalNG
2785
+ {
2786
+ public int Id { get ; set ; }
2787
+ public DependentNG DependentNG { get ; set ; }
2788
+ }
2789
+
2790
+ private class DependentNG
2791
+ {
2792
+ public int Id { get ; set ; }
2793
+ public PrincipalNG PrincipalNG { get ; set ; }
2794
+ }
2795
+
2796
+ private class PrincipalGN
2797
+ {
2798
+ public int Id { get ; set ; }
2799
+ public DependentGN DependentGN { get ; set ; }
2800
+ }
2801
+
2802
+ private class DependentGN
2803
+ {
2804
+ public int Id { get ; set ; }
2805
+ public PrincipalGN PrincipalGN { get ; set ; }
2806
+ }
2807
+
2532
2808
private class EarlyLearningCenter : DbContext
2533
2809
{
2534
2810
private readonly IServiceProvider _serviceProvider;
@@ -2576,6 +2852,65 @@ protected internal override void OnModelCreating(ModelBuilder modelBuilder)
2576
2852
} ) ;
2577
2853
2578
2854
modelBuilder. Entity < OptionalProduct > ( ) ;
2855
+
2856
+ modelBuilder. Entity < PrincipalNN > (
2857
+ b =>
2858
+ {
2859
+ b . HasOne ( e => e . DependentNN )
2860
+ . WithOne ( e => e . PrincipalNN )
2861
+ . HasForeignKey < DependentNN > ( e => e . Id ) ;
2862
+
2863
+ b . Property ( e => e . Id ) . ValueGeneratedNever ( ) ;
2864
+ } ) ;
2865
+
2866
+ modelBuilder. Entity < DependentNN > ( ) . Property ( e => e . Id ) . ValueGeneratedNever ( ) ;
2867
+
2868
+ modelBuilder. Entity < PrincipalGG > (
2869
+ b =>
2870
+ {
2871
+ b . HasOne ( e => e . DependentGG )
2872
+ . WithOne ( e => e . PrincipalGG )
2873
+ . HasForeignKey < DependentGG > ( e => e . Id ) ;
2874
+
2875
+ b . Property ( e => e . Id ) . ValueGeneratedOnAdd ( ) ;
2876
+ } ) ;
2877
+
2878
+ modelBuilder. Entity < DependentGG > ( ) . Property ( e => e . Id ) . ValueGeneratedOnAdd ( ) ;
2879
+
2880
+ modelBuilder. Entity < PrincipalNG > (
2881
+ b =>
2882
+ {
2883
+ b . HasOne ( e => e . DependentNG )
2884
+ . WithOne ( e => e . PrincipalNG )
2885
+ . HasForeignKey < DependentNG > ( e => e . Id ) ;
2886
+
2887
+ b . Property ( e => e . Id ) . ValueGeneratedNever ( ) ;
2888
+ } ) ;
2889
+
2890
+ modelBuilder. Entity < DependentNG > ( ) . Property ( e => e . Id ) . HasValueGenerator < DummyValueGenerator > ( ) ;
2891
+
2892
+ modelBuilder. Entity < PrincipalGN > (
2893
+ b =>
2894
+ {
2895
+ b . HasOne ( e => e . DependentGN )
2896
+ . WithOne ( e => e . PrincipalGN )
2897
+ . HasForeignKey < DependentGN > ( e => e . Id ) ;
2898
+
2899
+ b . Property ( e => e . Id ) . ValueGeneratedOnAdd ( ) ;
2900
+ } ) ;
2901
+
2902
+ modelBuilder. Entity < DependentGN > ( ) . Property ( e => e . Id ) . ValueGeneratedNever ( ) ;
2903
+ }
2904
+
2905
+ private class DummyValueGenerator : ValueGenerator < int >
2906
+ {
2907
+ private static int _value;
2908
+
2909
+ public override int Next( EntityEntry entry )
2910
+ => _value ++ ;
2911
+
2912
+ public override bool GeneratesTemporaryValues
2913
+ => false ;
2579
2914
}
2580
2915
2581
2916
protected internal override void OnConfiguring( DbContextOptionsBuilder optionsBuilder )
0 commit comments