Skip to content

Commit 0de13fd

Browse files
committed
Review updates.
1 parent 7d9746e commit 0de13fd

File tree

1 file changed

+152
-92
lines changed

1 file changed

+152
-92
lines changed

test/EFCore.SqlServer.FunctionalTests/OptimisticConcurrencySqlServerTest.cs

+152-92
Original file line numberDiff line numberDiff line change
@@ -36,38 +36,38 @@ await context
3636
[ConditionalTheory]
3737
[InlineData(true)]
3838
[InlineData(false)]
39-
public Task Ulong_row_version_with_TPH_and_owned_types(bool updateOwned)
40-
=> Row_version_with_owned_types<SuperFan, ulong>(updateOwned, Mapping.Tph, "ULongVersion");
39+
public Task Ulong_row_version_with_TPH_and_owned_types(bool updateOwnedFirst)
40+
=> Row_version_with_owned_types<SuperFan, ulong>(updateOwnedFirst, Mapping.Tph, "ULongVersion");
4141

4242
[ConditionalTheory]
4343
[InlineData(true)]
4444
[InlineData(false)]
45-
public Task Ulong_row_version_with_TPT_and_owned_types(bool updateOwned)
46-
=> Row_version_with_owned_types<SuperFanTpt, ulong>(updateOwned, Mapping.Tpt, "ULongVersion");
45+
public Task Ulong_row_version_with_TPT_and_owned_types(bool updateOwnedFirst)
46+
=> Row_version_with_owned_types<SuperFanTpt, ulong>(updateOwnedFirst, Mapping.Tpt, "ULongVersion");
4747

4848
[ConditionalTheory]
4949
[InlineData(true)]
5050
[InlineData(false)]
51-
public Task Ulong_row_version_with_TPC_and_owned_types(bool updateOwned)
52-
=> Row_version_with_owned_types<SuperFanTpc, ulong>(updateOwned, Mapping.Tpc, "ULongVersion");
51+
public Task Ulong_row_version_with_TPC_and_owned_types(bool updateOwnedFirst)
52+
=> Row_version_with_owned_types<SuperFanTpc, ulong>(updateOwnedFirst, Mapping.Tpc, "ULongVersion");
5353

5454
[ConditionalTheory]
5555
[InlineData(true)]
5656
[InlineData(false)]
57-
public Task Ulong_row_version_with_TPH_and_table_splitting(bool updateDependent)
58-
=> Row_version_with_table_splitting<StreetCircuit, City, ulong>(updateDependent, Mapping.Tph, "ULongVersion");
57+
public Task Ulong_row_version_with_TPH_and_table_splitting(bool updateDependentFirst)
58+
=> Row_version_with_table_splitting<StreetCircuit, City, ulong>(updateDependentFirst, Mapping.Tph, "ULongVersion");
5959

6060
[ConditionalTheory]
6161
[InlineData(true)]
6262
[InlineData(false)]
63-
public Task Ulong_row_version_with_TPT_and_table_splitting(bool updateDependent)
64-
=> Row_version_with_table_splitting<StreetCircuitTpt, CityTpt, ulong>(updateDependent, Mapping.Tpt, "ULongVersion");
63+
public Task Ulong_row_version_with_TPT_and_table_splitting(bool updateDependentFirst)
64+
=> Row_version_with_table_splitting<StreetCircuitTpt, CityTpt, ulong>(updateDependentFirst, Mapping.Tpt, "ULongVersion");
6565

6666
[ConditionalTheory]
6767
[InlineData(true)]
6868
[InlineData(false)]
69-
public Task Ulong_row_version_with_TPC_and_table_splitting(bool updateDependent)
70-
=> Row_version_with_table_splitting<StreetCircuitTpc, CityTpc, ulong>(updateDependent, Mapping.Tpc, "ULongVersion");
69+
public Task Ulong_row_version_with_TPC_and_table_splitting(bool updateDependentFirst)
70+
=> Row_version_with_table_splitting<StreetCircuitTpc, CityTpc, ulong>(updateDependentFirst, Mapping.Tpc, "ULongVersion");
7171
}
7272

7373
public class OptimisticConcurrencySqlServerTest : OptimisticConcurrencySqlServerTestBase<F1SqlServerFixture, byte[]>
@@ -80,38 +80,38 @@ public OptimisticConcurrencySqlServerTest(F1SqlServerFixture fixture)
8080
[ConditionalTheory]
8181
[InlineData(true)]
8282
[InlineData(false)]
83-
public Task Row_version_with_TPH_and_owned_types(bool updateOwned)
84-
=> Row_version_with_owned_types<SuperFan, List<byte>>(updateOwned, Mapping.Tph, "BinaryVersion");
83+
public Task Row_version_with_TPH_and_owned_types(bool updateOwnedFirst)
84+
=> Row_version_with_owned_types<SuperFan, List<byte>>(updateOwnedFirst, Mapping.Tph, "BinaryVersion");
8585

8686
[ConditionalTheory]
8787
[InlineData(true)]
8888
[InlineData(false)]
89-
public Task Row_version_with_TPT_and_owned_types(bool updateOwned)
90-
=> Row_version_with_owned_types<SuperFanTpt, List<byte>>(updateOwned, Mapping.Tpt, "BinaryVersion");
89+
public Task Row_version_with_TPT_and_owned_types(bool updateOwnedFirst)
90+
=> Row_version_with_owned_types<SuperFanTpt, List<byte>>(updateOwnedFirst, Mapping.Tpt, "BinaryVersion");
9191

9292
[ConditionalTheory]
9393
[InlineData(true)]
9494
[InlineData(false)]
95-
public Task Row_version_with_TPC_and_owned_types(bool updateOwned)
96-
=> Row_version_with_owned_types<SuperFanTpc, List<byte>>(updateOwned, Mapping.Tpc, "BinaryVersion");
95+
public Task Row_version_with_TPC_and_owned_types(bool updateOwnedFirst)
96+
=> Row_version_with_owned_types<SuperFanTpc, List<byte>>(updateOwnedFirst, Mapping.Tpc, "BinaryVersion");
9797

9898
[ConditionalTheory]
9999
[InlineData(true)]
100100
[InlineData(false)]
101-
public Task Ulong_row_version_with_TPH_and_table_splitting(bool updateDependent)
102-
=> Row_version_with_table_splitting<StreetCircuit, City, List<byte>>(updateDependent, Mapping.Tph, "BinaryVersion");
101+
public Task Ulong_row_version_with_TPH_and_table_splitting(bool updateDependentFirst)
102+
=> Row_version_with_table_splitting<StreetCircuit, City, List<byte>>(updateDependentFirst, Mapping.Tph, "BinaryVersion");
103103

104104
[ConditionalTheory]
105105
[InlineData(true)]
106106
[InlineData(false)]
107-
public Task Ulong_row_version_with_TPT_and_table_splitting(bool updateDependent)
108-
=> Row_version_with_table_splitting<StreetCircuitTpt, CityTpt, List<byte>>(updateDependent, Mapping.Tpt, "BinaryVersion");
107+
public Task Ulong_row_version_with_TPT_and_table_splitting(bool updateDependentFirst)
108+
=> Row_version_with_table_splitting<StreetCircuitTpt, CityTpt, List<byte>>(updateDependentFirst, Mapping.Tpt, "BinaryVersion");
109109

110110
[ConditionalTheory]
111111
[InlineData(true)]
112112
[InlineData(false)]
113-
public Task Ulong_row_version_with_TPC_and_table_splitting(bool updateDependent)
114-
=> Row_version_with_table_splitting<StreetCircuitTpc, CityTpc, List<byte>>(updateDependent, Mapping.Tpc, "BinaryVersion");
113+
public Task Ulong_row_version_with_TPC_and_table_splitting(bool updateDependentFirst)
114+
=> Row_version_with_table_splitting<StreetCircuitTpc, CityTpc, List<byte>>(updateDependentFirst, Mapping.Tpc, "BinaryVersion");
115115
}
116116

117117
public abstract class OptimisticConcurrencySqlServerTestBase<TFixture, TRowVersion>
@@ -130,7 +130,7 @@ protected enum Mapping
130130
Tpc
131131
}
132132

133-
protected async Task Row_version_with_owned_types<TEntity, TVersion>(bool updateOwned, Mapping mapping, string propertyName)
133+
protected async Task Row_version_with_owned_types<TEntity, TVersion>(bool updateOwnedFirst, Mapping mapping, string propertyName)
134134
where TEntity : class, ISuperFan
135135
{
136136
await using var c = CreateF1Context();
@@ -146,69 +146,100 @@ await c.Database.CreateExecutionStrategy().ExecuteAsync(
146146

147147
var fanEntry = c.Entry(fan);
148148
var swagEntry = fanEntry.Reference(s => s.Swag).TargetEntry!;
149-
var originalFanVersion = fanEntry.Property<TVersion>(propertyName).CurrentValue;
150-
var originalSwagVersion = default(TVersion);
149+
var fanVersion1 = fanEntry.Property<TVersion>(propertyName).CurrentValue;
150+
var swagVersion1 = default(TVersion);
151151

152-
if (mapping == Mapping.Tph)
152+
if (mapping == Mapping.Tph) // Issue #29750
153153
{
154-
originalSwagVersion
155-
= swagEntry.Property<TVersion>(synthesizedPropertyName).CurrentValue;
154+
swagVersion1 = swagEntry.Property<TVersion>(synthesizedPropertyName).CurrentValue;
156155

157-
Assert.Equal(originalFanVersion, originalSwagVersion);
158-
}
159-
160-
if (updateOwned)
161-
{
162-
fan.Swag.Stuff += "+";
163-
}
164-
else
165-
{
166-
fan.Name += "+";
156+
Assert.Equal(fanVersion1, swagVersion1);
167157
}
168158

169159
await using var innerContext = CreateF1Context();
170160
UseTransaction(innerContext.Database, transaction);
171161
var fanInner = innerContext.Set<TEntity>().Single(e => e.Name == "Alice");
172162

173-
if (updateOwned)
163+
if (updateOwnedFirst)
174164
{
165+
fan.Swag.Stuff += "+";
175166
fanInner.Swag.Stuff += "-";
176167
}
177168
else
178169
{
179170
fanInner.Name += "-";
171+
fan.Name += "+";
180172
}
181173

182174
await innerContext.SaveChangesAsync();
183175

184-
if (!updateOwned || mapping != Mapping.Tpt) // Issue #22060
176+
if (updateOwnedFirst && mapping == Mapping.Tpt) // Issue #22060
185177
{
186-
await Assert.ThrowsAnyAsync<DbUpdateConcurrencyException>(() => context.SaveChangesAsync());
178+
await context.SaveChangesAsync();
179+
return;
180+
}
187181

188-
await fanEntry.ReloadAsync();
189-
await swagEntry.ReloadAsync();
182+
await Assert.ThrowsAnyAsync<DbUpdateConcurrencyException>(() => context.SaveChangesAsync());
190183

191-
await context.SaveChangesAsync();
184+
await fanEntry.ReloadAsync();
185+
await swagEntry.ReloadAsync();
192186

193-
var fanVersion = fanEntry.Property<TVersion>(propertyName).CurrentValue;
194-
Assert.NotEqual(originalFanVersion, fanVersion);
187+
await context.SaveChangesAsync();
195188

196-
if (mapping == Mapping.Tph)
197-
{
198-
var swagVersion = swagEntry.Property<TVersion>(synthesizedPropertyName).CurrentValue;
199-
Assert.Equal(fanVersion, swagVersion);
200-
Assert.NotEqual(originalSwagVersion, swagVersion);
201-
}
189+
var fanVersion2 = fanEntry.Property<TVersion>(propertyName).CurrentValue;
190+
Assert.NotEqual(fanVersion1, fanVersion2);
191+
192+
var swagVersion2 = default(TVersion);
193+
if (mapping == Mapping.Tph) // Issue #29750
194+
{
195+
swagVersion2 = swagEntry.Property<TVersion>(synthesizedPropertyName).CurrentValue;
196+
Assert.Equal(fanVersion2, swagVersion2);
197+
Assert.NotEqual(swagVersion1, swagVersion2);
198+
}
199+
200+
await innerContext.Entry(fanInner).ReloadAsync();
201+
await innerContext.Entry(fanInner.Swag).ReloadAsync();
202+
203+
if (updateOwnedFirst)
204+
{
205+
fanInner.Name += "-";
206+
fan.Name += "+";
202207
}
203208
else
209+
{
210+
fan.Swag.Stuff += "+";
211+
fanInner.Swag.Stuff += "-";
212+
}
213+
214+
await innerContext.SaveChangesAsync();
215+
216+
if (!updateOwnedFirst && mapping == Mapping.Tpt) // Issue #22060
204217
{
205218
await context.SaveChangesAsync();
219+
return;
220+
}
221+
222+
await Assert.ThrowsAnyAsync<DbUpdateConcurrencyException>(() => context.SaveChangesAsync());
223+
224+
await fanEntry.ReloadAsync();
225+
await swagEntry.ReloadAsync();
226+
227+
await context.SaveChangesAsync();
228+
229+
var fanVersion3 = fanEntry.Property<TVersion>(propertyName).CurrentValue;
230+
Assert.NotEqual(fanVersion2, fanVersion3);
231+
232+
if (mapping == Mapping.Tph) // Issue #29750
233+
{
234+
var swagVersion3 = swagEntry.Property<TVersion>(synthesizedPropertyName).CurrentValue;
235+
Assert.Equal(fanVersion3, swagVersion3);
236+
Assert.NotEqual(swagVersion2, swagVersion3);
206237
}
207238
});
208239
}
209240

210241
protected async Task Row_version_with_table_splitting<TEntity, TCity, TVersion>(
211-
bool updateDependent,
242+
bool updateDependentFirst,
212243
Mapping mapping,
213244
string propertyName)
214245
where TEntity : class, IStreetCircuit<TCity>
@@ -227,71 +258,100 @@ await c.Database.CreateExecutionStrategy().ExecuteAsync(
227258

228259
var circuitEntry = c.Entry(circuit);
229260
var cityEntry = circuitEntry.Reference(s => s.City).TargetEntry!;
230-
var originalCircuitVersion = circuitEntry.Property<TVersion>(propertyName).CurrentValue;
231-
var originalCityVersion = default(TVersion);
261+
var circuitVersion1 = circuitEntry.Property<TVersion>(propertyName).CurrentValue;
262+
var cityVersion1 = default(TVersion);
232263

233-
if (mapping == Mapping.Tph)
264+
if (mapping == Mapping.Tph) // Issue #29750
234265
{
235-
originalCityVersion
236-
= cityEntry.Property<TVersion>(synthesizedPropertyName).CurrentValue;
266+
cityVersion1 = cityEntry.Property<TVersion>(synthesizedPropertyName).CurrentValue;
237267

238-
Assert.Equal(originalCircuitVersion, originalCityVersion);
268+
Assert.Equal(circuitVersion1, cityVersion1);
239269
}
240270

241-
if (updateDependent)
271+
await using var innerContext = CreateF1Context();
272+
UseTransaction(innerContext.Database, transaction);
273+
var circuitInner = innerContext.Set<TEntity>().Include(e => e.City).Single(e => e.Name == "Monaco");
274+
275+
if (updateDependentFirst)
242276
{
243277
circuit.City.Name += "+";
278+
circuitInner.City.Name += "-";
244279
}
245280
else
246281
{
247282
circuit.Name += "+";
283+
circuitInner.Name += "-";
248284
}
249285

250-
await using var innerContext = CreateF1Context();
251-
UseTransaction(innerContext.Database, transaction);
252-
var fanInner = innerContext.Set<TEntity>().Include(e => e.City).Single(e => e.Name == "Monaco");
253-
254-
if (updateDependent)
286+
if (mapping == Mapping.Tpc) // Issue #29751.
255287
{
256-
fanInner.City.Name += "-";
288+
await Assert.ThrowsAsync<InvalidOperationException>(() => innerContext.SaveChangesAsync());
289+
return;
257290
}
258-
else
291+
292+
await innerContext.SaveChangesAsync();
293+
294+
if (updateDependentFirst && mapping == Mapping.Tpt) // Issue #22060
259295
{
260-
fanInner.Name += "-";
296+
await context.SaveChangesAsync();
297+
return;
261298
}
262299

263-
if (mapping == Mapping.Tpc)
300+
await Assert.ThrowsAnyAsync<DbUpdateConcurrencyException>(() => context.SaveChangesAsync());
301+
302+
await circuitEntry.ReloadAsync();
303+
await cityEntry.ReloadAsync();
304+
305+
await context.SaveChangesAsync();
306+
307+
var circuitVersion2 = circuitEntry.Property<TVersion>(propertyName).CurrentValue;
308+
Assert.NotEqual(circuitVersion1, circuitVersion2);
309+
310+
var cityVersion2 = default(TVersion);
311+
if (mapping == Mapping.Tph) // Issue #29750
264312
{
265-
await Assert.ThrowsAsync<InvalidOperationException>(() => innerContext.SaveChangesAsync());
313+
cityVersion2 = cityEntry.Property<TVersion>(synthesizedPropertyName).CurrentValue;
314+
Assert.Equal(circuitVersion2, cityVersion2);
315+
Assert.NotEqual(cityVersion1, cityVersion2);
316+
}
317+
318+
await innerContext.Entry(circuitInner).ReloadAsync();
319+
await innerContext.Entry(circuitInner.City).ReloadAsync();
266320

321+
if (updateDependentFirst)
322+
{
323+
circuit.Name += "+";
324+
circuitInner.Name += "-";
267325
}
268326
else
269327
{
270-
await innerContext.SaveChangesAsync();
328+
circuit.City.Name += "+";
329+
circuitInner.City.Name += "-";
330+
}
271331

272-
if (!updateDependent || mapping != Mapping.Tpt) // Issue #22060
273-
{
274-
await Assert.ThrowsAnyAsync<DbUpdateConcurrencyException>(() => context.SaveChangesAsync());
332+
await innerContext.SaveChangesAsync();
275333

276-
await circuitEntry.ReloadAsync();
277-
await cityEntry.ReloadAsync();
334+
if (!updateDependentFirst && mapping == Mapping.Tpt) // Issue #22060
335+
{
336+
await context.SaveChangesAsync();
337+
return;
338+
}
278339

279-
await context.SaveChangesAsync();
340+
await Assert.ThrowsAnyAsync<DbUpdateConcurrencyException>(() => context.SaveChangesAsync());
280341

281-
var circuitVersion = circuitEntry.Property<TVersion>(propertyName).CurrentValue;
282-
Assert.NotEqual(originalCircuitVersion, circuitVersion);
342+
await circuitEntry.ReloadAsync();
343+
await cityEntry.ReloadAsync();
283344

284-
if (mapping == Mapping.Tph)
285-
{
286-
var cityVersion = cityEntry.Property<TVersion>(synthesizedPropertyName).CurrentValue;
287-
Assert.Equal(circuitVersion, cityVersion);
288-
Assert.NotEqual(originalCityVersion, cityVersion);
289-
}
290-
}
291-
else
292-
{
293-
await context.SaveChangesAsync();
294-
}
345+
await context.SaveChangesAsync();
346+
347+
var circuitVersion3 = circuitEntry.Property<TVersion>(propertyName).CurrentValue;
348+
Assert.NotEqual(circuitVersion2, circuitVersion3);
349+
350+
if (mapping == Mapping.Tph) // Issue #29750
351+
{
352+
var cityVersion3 = cityEntry.Property<TVersion>(synthesizedPropertyName).CurrentValue;
353+
Assert.Equal(circuitVersion3, cityVersion3);
354+
Assert.NotEqual(cityVersion2, cityVersion3);
295355
}
296356
});
297357
}

0 commit comments

Comments
 (0)