@@ -52,10 +52,7 @@ public void TestDbContext4()
52
52
[ TestMethod ]
53
53
public void TestDbContext5 ( )
54
54
{
55
- Services . Configure < AppConfigOptions > ( options =>
56
- {
57
- options . DbConnectionString = MemoryConnectionString ;
58
- } ) ;
55
+ Services . Configure < AppConfigOptions > ( options => { options . DbConnectionString = MemoryConnectionString ; } ) ;
59
56
var dbContext = CreateDbContext < CustomDbContext5 > ( null ) ;
60
57
var student = GenerateStudent ( ) ;
61
58
dbContext . Set < Student > ( ) . Add ( student ) ;
@@ -79,10 +76,7 @@ public void TestDbContext6()
79
76
[ TestMethod ]
80
77
public void TestDbContext7 ( )
81
78
{
82
- Services . Configure < AppConfigOptions > ( options =>
83
- {
84
- options . DbConnectionString = MemoryConnectionString ;
85
- } ) ;
79
+ Services . Configure < AppConfigOptions > ( options => { options . DbConnectionString = MemoryConnectionString ; } ) ;
86
80
var dbContext = CreateDbContext < CustomDbContext7 > ( null ) ;
87
81
var student = GenerateStudent ( ) ;
88
82
dbContext . Set < Student > ( ) . Add ( student ) ;
@@ -128,9 +122,9 @@ private static Student GenerateStudent()
128
122
129
123
private static Student VerifyStudent ( DbContext dbContext , Guid id , bool isTracking = false )
130
124
{
131
- var student = isTracking ?
132
- dbContext . Set < Student > ( ) . AsTracking ( ) . Include ( s => s . Hobbies ) . FirstOrDefault ( s => s . Id == id ) :
133
- dbContext . Set < Student > ( ) . AsNoTracking ( ) . Include ( s => s . Hobbies ) . FirstOrDefault ( s => s . Id == id ) ;
125
+ var student = isTracking
126
+ ? dbContext . Set < Student > ( ) . AsTracking ( ) . Include ( s => s . Hobbies ) . FirstOrDefault ( s => s . Id == id )
127
+ : dbContext . Set < Student > ( ) . AsNoTracking ( ) . Include ( s => s . Hobbies ) . FirstOrDefault ( s => s . Id == id ) ;
134
128
Assert . IsNotNull ( student ) ;
135
129
return student ;
136
130
}
@@ -202,6 +196,83 @@ public async Task TestSoftDeleteAsync()
202
196
}
203
197
}
204
198
199
+ [ TestMethod ]
200
+ public async Task TestModifierBySoftDeleteAsync ( )
201
+ {
202
+ var creatorUserContext = new CustomUserContext ( "1" ) ;
203
+ Services . Configure < AuditEntityOptions > ( options => options . UserIdType = typeof ( int ) ) ;
204
+ Services . AddSingleton < IUserContext > ( creatorUserContext ) ;
205
+
206
+ IServiceProvider serviceProvider = default ! ;
207
+ var dbContext = await CreateDbContextAsync < CustomDbContext > ( dbContextBuilder =>
208
+ {
209
+ dbContextBuilder . UseFilter ( ) ;
210
+ dbContextBuilder . UseInMemoryDatabase ( MemoryConnectionString ) ;
211
+ } , sp => serviceProvider = sp ) ;
212
+ var goods = new Goods ( )
213
+ {
214
+ Name = "masa" ,
215
+ Logs = new List < OperationLog > ( )
216
+ {
217
+ new ( "initialize" ) ,
218
+ new ( "initialize2" ) ,
219
+ }
220
+ } ;
221
+ await dbContext . Set < Goods > ( ) . AddAsync ( goods ) ;
222
+ await dbContext . SaveChangesAsync ( ) ;
223
+
224
+ var goodsCreate = await dbContext . Set < Goods > ( ) . Include ( g => g . Logs ) . FirstOrDefaultAsync ( g => g . Name == "masa" ) ;
225
+ Assert . IsNotNull ( goodsCreate ) ;
226
+
227
+ var modifierByCrate = goodsCreate . Modifier ;
228
+ var modificationTimeByCreate = goodsCreate . ModificationTime ;
229
+
230
+ Assert . AreEqual ( 2 , goodsCreate . Logs . Count ) ;
231
+ var log1 = goods . Logs . FirstOrDefault ( log => log . Name == "initialize" ) ;
232
+ Assert . IsNotNull ( log1 ) ;
233
+ var log2 = goods . Logs . FirstOrDefault ( log => log . Name == "initialize2" ) ;
234
+ Assert . IsNotNull ( log2 ) ;
235
+
236
+ creatorUserContext . SetUserId ( "2" ) ;
237
+
238
+ var inputModificationTime = DateTime . UtcNow . AddDays ( - 1 ) ;
239
+ log1 . SetDeleted ( true , 3 , inputModificationTime ) ;
240
+ goods . Logs . Clear ( ) ;
241
+ dbContext . Set < Goods > ( ) . Update ( goods ) ;
242
+ await dbContext . SaveChangesAsync ( ) ;
243
+
244
+ var goodsByUpdate = await dbContext . Set < Goods > ( ) . IgnoreQueryFilters ( ) . Include ( g => g . Logs ) . FirstOrDefaultAsync ( ) ;
245
+ Assert . IsNotNull ( goodsByUpdate ) ;
246
+
247
+ Assert . AreEqual ( 2 , goodsByUpdate . Logs . Count ) ;
248
+ var log1ByUpdate = goodsByUpdate . Logs . FirstOrDefault ( log => log . Name == "initialize" ) ;
249
+ Assert . IsNotNull ( log1ByUpdate ) ;
250
+
251
+ Assert . AreEqual ( true , log1ByUpdate . IsDeleted ) ;
252
+ Assert . AreEqual ( 3 , log1ByUpdate . Modifier ) ;
253
+ Assert . AreEqual ( inputModificationTime , log1ByUpdate . ModificationTime ) ;
254
+
255
+ var log1ByUpdate2 = goodsByUpdate . Logs . FirstOrDefault ( log => log . Name == "initialize2" ) ;
256
+ Assert . IsNotNull ( log1ByUpdate2 ) ;
257
+
258
+ Assert . AreEqual ( true , log1ByUpdate2 . IsDeleted ) ;
259
+ Assert . AreEqual ( 2 , log1ByUpdate2 . Modifier ) ;
260
+ Assert . AreNotEqual ( modificationTimeByCreate , log1ByUpdate . ModificationTime ) ;
261
+
262
+ var goodsByUpdateAgain = await dbContext . Set < Goods > ( ) . AsTracking ( ) . IgnoreQueryFilters ( ) . Include ( g => g . Logs ) . FirstOrDefaultAsync ( ) ;
263
+ Assert . IsNotNull ( goodsByUpdateAgain ) ;
264
+ var modificationTime = DateTime . Parse ( "2022-01-01 00:00:00" ) ;
265
+ goodsByUpdateAgain . SetDeleted ( true , 10 , modificationTime ) ;
266
+ dbContext . Set < Goods > ( ) . Remove ( goodsByUpdateAgain ) ;
267
+ await dbContext . SaveChangesAsync ( ) ;
268
+
269
+ var goodsByDelete = await dbContext . Set < Goods > ( ) . AsNoTracking ( ) . IgnoreQueryFilters ( ) . FirstOrDefaultAsync ( g => g . Name == "masa" ) ;
270
+ Assert . IsNotNull ( goodsByDelete ) ;
271
+
272
+ Assert . AreEqual ( 10 , goodsByDelete . Modifier ) ;
273
+ Assert . AreEqual ( modificationTime , goodsByDelete . ModificationTime ) ;
274
+ }
275
+
205
276
#endregion
206
277
207
278
#region Test ConnectionString
@@ -215,10 +286,8 @@ public async Task TestModifyConnectionString()
215
286
Services . AddSingleton < IConfiguration > ( configuration ) ;
216
287
217
288
IServiceProvider serviceProvider = default ! ;
218
- var dbContext = await CreateDbContextAsync < CustomDbContext > ( optionsBuilder =>
219
- {
220
- optionsBuilder . UseSqlite ( ) ;
221
- } , sp => serviceProvider = sp ) ;
289
+ var dbContext =
290
+ await CreateDbContextAsync < CustomDbContext > ( optionsBuilder => { optionsBuilder . UseSqlite ( ) ; } , sp => serviceProvider = sp ) ;
222
291
223
292
var connectionStringProvider = serviceProvider . GetService < IConnectionStringProvider > ( ) ;
224
293
Assert . IsNotNull ( connectionStringProvider ) ;
@@ -269,31 +338,20 @@ public async Task TestUseConfigurationAndSpecify()
269
338
. Build ( ) ;
270
339
Services . AddSingleton < IConfiguration > ( configuration ) ;
271
340
272
- await CreateDbContextAsync < CustomDbContext > ( optionsBuilder =>
273
- {
274
- optionsBuilder . UseSqlite ( ) ;
275
- } ) ;
341
+ await CreateDbContextAsync < CustomDbContext > ( optionsBuilder => { optionsBuilder . UseSqlite ( ) ; } ) ;
276
342
await Assert . ThrowsExceptionAsync < ArgumentException > ( async ( ) =>
277
343
{
278
- await CreateDbContextAsync < CustomDbContext2 > ( optionsBuilder =>
279
- {
280
- optionsBuilder . UseSqlite ( SqliteConnectionString ) ;
281
- } ) ;
344
+ await CreateDbContextAsync < CustomDbContext2 > ( optionsBuilder => { optionsBuilder . UseSqlite ( SqliteConnectionString ) ; } ) ;
282
345
} ) ;
283
346
}
284
347
285
348
[ TestMethod ]
286
349
public async Task TestAddMultiDbContextAsync ( )
287
350
{
288
- Services . AddMasaDbContext < CustomDbContext > ( dbContextBuilder =>
289
- {
290
- dbContextBuilder . UseInMemoryDatabase ( MemoryConnectionString ) ;
291
- } ) ;
351
+ Services . AddMasaDbContext < CustomDbContext > ( dbContextBuilder => { dbContextBuilder . UseInMemoryDatabase ( MemoryConnectionString ) ; } ) ;
292
352
IServiceProvider serviceProvider = default ! ;
293
- var customDbContext2 = await CreateDbContextAsync < CustomDbContext2 > ( dbContextBuilder =>
294
- {
295
- dbContextBuilder . UseInMemoryDatabase ( MemoryConnectionString ) ;
296
- } , sp => serviceProvider = sp ) ;
353
+ var customDbContext2 = await CreateDbContextAsync < CustomDbContext2 > (
354
+ dbContextBuilder => { dbContextBuilder . UseInMemoryDatabase ( MemoryConnectionString ) ; } , sp => serviceProvider = sp ) ;
297
355
298
356
var customDbContext = serviceProvider . GetService < CustomDbContext > ( ) ;
299
357
Assert . IsNotNull ( customDbContext ) ;
@@ -352,8 +410,9 @@ await dbContext.Set<Goods>().AddAsync(new Goods()
352
410
var creationTimeByCreate = goodsByCreate . CreationTime ;
353
411
var modifierByCreate = goodsByCreate . Modifier ;
354
412
var modificationTimeByCreate = goodsByCreate . ModificationTime ;
355
- Assert . AreEqual ( expectedCreator , goodsByCreate . Creator ) ;
356
- Assert . AreEqual ( expectedCreator , goodsByCreate . Modifier ) ;
413
+
414
+ Assert . AreEqual ( expectedCreator , creatorByCreate ) ;
415
+ Assert . AreEqual ( expectedCreator , modifierByCreate ) ;
357
416
358
417
customUserContext . SetUserId ( modifier ? . ToString ( ) ) ;
359
418
goodsByCreate . Name = "masa1" ;
@@ -453,17 +512,73 @@ await dbContext.Set<Goods2>().AddAsync(new Goods2()
453
512
Assert . AreNotEqual ( modificationTimeByUpdate , goodsByUpdate . ModificationTime ) ;
454
513
}
455
514
515
+ [ DataRow ( 1 , 2 , 1 , "2023-01-01 00:00:00" , "2023-01-01 00:00:00" , 3 , 3 , "2023-01-02 00:00:00" , "2023-01-02 00:00:00" ) ]
516
+ [ DataTestMethod ]
517
+ public async Task TestAddOrUpdateOrDeleteWhenUserIdIsIntAsyncBySpecifyUserIdAndTime (
518
+ int inputCreator , int currentCreator , int expectedCreator ,
519
+ string inputCreationTimeStr , string expectedCreationTimeStr ,
520
+ int inputModifier , int expectedModifier ,
521
+ string inputModificationTimeStr , string expectedModificationTimeStr )
522
+ {
523
+ DateTime inputCreationTime = DateTime . Parse ( inputCreationTimeStr ) , expectedCreationTime = DateTime . Parse ( expectedCreationTimeStr ) ;
524
+ DateTime inputModificationTime = DateTime . Parse ( inputModificationTimeStr ) ,
525
+ expectedModificationTime = DateTime . Parse ( expectedModificationTimeStr ) ;
526
+ Services . Configure < AuditEntityOptions > ( options => options . UserIdType = typeof ( int ) ) ;
527
+
528
+ var customUserContext = new CustomUserContext ( currentCreator . ToString ( ) ) ;
529
+ Services . AddSingleton < IUserContext > ( customUserContext ) ;
530
+
531
+ var connectionString = MemoryConnectionString ;
532
+ var dbContext = await CreateDbContextAsync < CustomDbContext > ( dbContextBuilder =>
533
+ {
534
+ dbContextBuilder
535
+ . UseInMemoryDatabase ( connectionString )
536
+ . UseQueryTrackingBehavior ( QueryTrackingBehavior . TrackAll )
537
+ . UseFilter ( ) ;
538
+ } ) ;
539
+ Assert . IsNotNull ( dbContext ) ;
540
+ var goods = new Goods ( "masa" , inputCreator , inputCreationTime , inputModifier , inputModificationTime ) ;
541
+ await dbContext . Set < Goods > ( ) . AddAsync ( goods ) ;
542
+ await dbContext . SaveChangesAsync ( ) ;
543
+
544
+ var goodsByCreate = await dbContext . Set < Goods > ( ) . FirstOrDefaultAsync ( ) ;
545
+ Assert . IsNotNull ( goodsByCreate ) ;
546
+ var creatorByCreate = goodsByCreate . Creator ;
547
+ var creationTimeByCreate = goodsByCreate . CreationTime ;
548
+ var modifierByCreate = goodsByCreate . Modifier ;
549
+ var modificationTimeByCreate = goodsByCreate . ModificationTime ;
550
+ Assert . AreEqual ( expectedCreator , creatorByCreate ) ;
551
+ Assert . AreEqual ( expectedCreationTime , creationTimeByCreate ) ;
552
+ Assert . AreEqual ( expectedModifier , modifierByCreate ) ;
553
+ Assert . AreEqual ( expectedModificationTime , modificationTimeByCreate ) ;
554
+
555
+ customUserContext . SetUserId ( ( currentCreator + 5 ) . ToString ( ) ) ;
556
+ goodsByCreate . UpdateName ( "masa1" , inputCreator + 2 , inputCreationTime . AddDays ( 1 ) , inputModifier + 3 ,
557
+ inputModificationTime . AddDays ( 2 ) ) ;
558
+ dbContext . Set < Goods > ( ) . Update ( goodsByCreate ) ;
559
+ await dbContext . SaveChangesAsync ( ) ;
560
+
561
+ var goodsByUpdate = await dbContext . Set < Goods > ( ) . FirstOrDefaultAsync ( ) ;
562
+ Assert . IsNotNull ( goodsByUpdate ) ;
563
+ var creatorByUpdate = goodsByUpdate . Creator ;
564
+ var creationTimeByUpdate = goodsByUpdate . CreationTime ;
565
+ var modifierByUpdate = goodsByUpdate . Modifier ;
566
+ var modificationTimeByUpdate = goodsByUpdate . ModificationTime ;
567
+ Assert . AreEqual ( inputCreator + 2 , creatorByUpdate ) ;
568
+ Assert . AreEqual ( inputCreationTime . AddDays ( 1 ) , creationTimeByUpdate ) ;
569
+ Assert . AreEqual ( currentCreator + 5 , modifierByUpdate ) ;
570
+ Assert . AreNotEqual ( expectedModificationTime , modificationTimeByUpdate ) ;
571
+ Assert . AreNotEqual ( inputModificationTime . AddDays ( 2 ) , modificationTimeByUpdate ) ;
572
+ }
573
+
456
574
#endregion
457
575
458
576
#region Test Model Mapping
459
577
460
578
[ TestMethod ]
461
579
public void TestCustomTableName ( )
462
580
{
463
- var dbContext = CreateDbContext < CustomDbContext > ( dbContext =>
464
- {
465
- dbContext . UseInMemoryDatabase ( MemoryConnectionString ) ;
466
- } ) ;
581
+ var dbContext = CreateDbContext < CustomDbContext > ( dbContext => { dbContext . UseInMemoryDatabase ( MemoryConnectionString ) ; } ) ;
467
582
var entityTableName = dbContext . Model . FindEntityType ( typeof ( Student ) ) ? . GetTableName ( ) ;
468
583
469
584
Assert . AreEqual ( "masa_students" , entityTableName ) ;
@@ -476,10 +591,7 @@ public void TestCustomTableName()
476
591
[ TestMethod ]
477
592
public void TestQueryTrackingBehaviorByDefault ( )
478
593
{
479
- var dbContext = CreateDbContext < CustomDbContext > ( dbContext =>
480
- {
481
- dbContext . UseInMemoryDatabase ( MemoryConnectionString ) ;
482
- } ) ;
594
+ var dbContext = CreateDbContext < CustomDbContext > ( dbContext => { dbContext . UseInMemoryDatabase ( MemoryConnectionString ) ; } ) ;
483
595
Assert . AreEqual ( QueryTrackingBehavior . NoTracking , dbContext . ChangeTracker . QueryTrackingBehavior ) ;
484
596
}
485
597
0 commit comments