@@ -3256,6 +3256,122 @@ public virtual Task Add_required_primitve_collection_with_custom_converter_and_c
3256
3256
Assert . Single ( customersTable . PrimaryKey ! . Columns ) ) ;
3257
3257
} ) ;
3258
3258
3259
+ [ ConditionalFact ]
3260
+ public virtual Task Multiop_drop_table_and_create_the_same_table_in_one_migration ( )
3261
+ => TestComposite (
3262
+ [
3263
+ builder => builder . Entity (
3264
+ "Customer" , e =>
3265
+ {
3266
+ e . Property < int > ( "Id" ) . ValueGeneratedOnAdd ( ) ;
3267
+ e . Property < string > ( "Name" ) ;
3268
+ e . HasKey ( "Id" ) ;
3269
+ e . ToTable ( "Customers" ) ;
3270
+ } ) ,
3271
+ builder => { } ,
3272
+ builder => builder . Entity (
3273
+ "Customer" , e =>
3274
+ {
3275
+ e . Property < int > ( "Id" ) . ValueGeneratedOnAdd ( ) ;
3276
+ e . Property < string > ( "Name" ) ;
3277
+ e . HasKey ( "Id" ) ;
3278
+
3279
+ e . ToTable ( "Customers" ) ;
3280
+ } )
3281
+ ] ,
3282
+ model => { } ) ;
3283
+
3284
+ [ ConditionalFact ]
3285
+ public virtual Task Multiop_create_table_and_drop_it_in_one_migration ( )
3286
+ => TestComposite (
3287
+ [
3288
+ builder => { } ,
3289
+ builder => builder . Entity (
3290
+ "Customer" , e =>
3291
+ {
3292
+ e . Property < int > ( "Id" ) . ValueGeneratedOnAdd ( ) ;
3293
+ e . Property < string > ( "Name" ) ;
3294
+ e . HasKey ( "Id" ) ;
3295
+
3296
+ e . ToTable ( "Customers" ) ;
3297
+ } ) ,
3298
+ builder => { } ,
3299
+ ] ,
3300
+ model => { } ) ;
3301
+
3302
+ [ ConditionalFact ]
3303
+ public virtual Task Multiop_rename_table_and_drop ( )
3304
+ => TestComposite (
3305
+ [
3306
+ builder => builder . Entity (
3307
+ "Customer" , e =>
3308
+ {
3309
+ e . Property < int > ( "Id" ) . ValueGeneratedOnAdd ( ) ;
3310
+ e . Property < string > ( "Name" ) ;
3311
+ e . HasKey ( "Id" ) ;
3312
+
3313
+ e . ToTable ( "Customers" ) ;
3314
+ } ) ,
3315
+ builder => builder . Entity (
3316
+ "Customer" , e =>
3317
+ {
3318
+ e . Property < int > ( "Id" ) . ValueGeneratedOnAdd ( ) ;
3319
+ e . Property < string > ( "Name" ) ;
3320
+ e . HasKey ( "Id" ) ;
3321
+
3322
+ e . ToTable ( "NewCustomers" ) ;
3323
+ } ) ,
3324
+ builder => { } ,
3325
+ ] ,
3326
+ model => { } ) ;
3327
+
3328
+ [ ConditionalFact ]
3329
+ public virtual Task Multiop_rename_table_and_create_new_table_with_the_old_name ( )
3330
+ => TestComposite (
3331
+ [
3332
+ builder => builder . Entity (
3333
+ "Customer" , e =>
3334
+ {
3335
+ e . Property < int > ( "Id" ) . ValueGeneratedOnAdd ( ) ;
3336
+ e . Property < string > ( "Name" ) ;
3337
+ e . HasKey ( "Id" ) ;
3338
+
3339
+ e . ToTable ( "Customers" ) ;
3340
+ } ) ,
3341
+ builder => builder . Entity (
3342
+ "Customer" , e =>
3343
+ {
3344
+ e . Property < int > ( "Id" ) . ValueGeneratedOnAdd ( ) ;
3345
+ e . Property < string > ( "Name" ) ;
3346
+ e . HasKey ( "Id" ) ;
3347
+
3348
+ e . ToTable ( "NewCustomers" ) ;
3349
+ } ) ,
3350
+ builder =>
3351
+ {
3352
+ builder . Entity (
3353
+ "Customer" , e =>
3354
+ {
3355
+ e . Property < int > ( "Id" ) . ValueGeneratedOnAdd ( ) ;
3356
+ e . Property < string > ( "Name" ) ;
3357
+ e . HasKey ( "Id" ) ;
3358
+
3359
+ e . ToTable ( "NewCustomers" ) ;
3360
+ } ) ;
3361
+
3362
+ builder . Entity (
3363
+ "AnotherCustomer" , e =>
3364
+ {
3365
+ e . Property < int > ( "Id" ) . ValueGeneratedOnAdd ( ) ;
3366
+ e . Property < string > ( "Name" ) ;
3367
+ e . HasKey ( "Id" ) ;
3368
+
3369
+ e . ToTable ( "Customers" ) ;
3370
+ } ) ;
3371
+ } ,
3372
+ ] ,
3373
+ model => { } ) ;
3374
+
3259
3375
protected class Person
3260
3376
{
3261
3377
public int Id { get ; set ; }
@@ -3305,6 +3421,62 @@ protected virtual Task Test(
3305
3421
MigrationsSqlGenerationOptions migrationsSqlGenerationOptions = MigrationsSqlGenerationOptions . Default )
3306
3422
=> Test ( _ => { } , buildSourceAction , buildTargetAction , asserter , withConventions , migrationsSqlGenerationOptions ) ;
3307
3423
3424
+ protected virtual Task TestComposite (
3425
+ List < Action < ModelBuilder > > buildActions ,
3426
+ Action < DatabaseModel > asserter ,
3427
+ bool withConventions = true ,
3428
+ MigrationsSqlGenerationOptions migrationsSqlGenerationOptions = MigrationsSqlGenerationOptions . Default )
3429
+ {
3430
+ if ( buildActions . Count < 3 )
3431
+ {
3432
+ throw new InvalidOperationException ( "You need at least 3 build actions for the composite case." ) ;
3433
+ }
3434
+
3435
+ var context = CreateContext ( ) ;
3436
+ var modelDiffer = context . GetService < IMigrationsModelDiffer > ( ) ;
3437
+ var modelRuntimeInitializer = context . GetService < IModelRuntimeInitializer > ( ) ;
3438
+
3439
+ var models = new List < IModel > ( ) ;
3440
+ var preSnapshotSourceModel = default ( IModel ) ;
3441
+ for ( var i = 0 ; i < buildActions . Count ; i ++ )
3442
+ {
3443
+ var modelBuilder = CreateModelBuilder ( withConventions ) ;
3444
+ buildActions [ i ] ( modelBuilder ) ;
3445
+
3446
+ var preSnapshotModel = modelRuntimeInitializer . Initialize (
3447
+ ( IModel ) modelBuilder . Model , designTime : true , validationLogger : null ) ;
3448
+
3449
+ if ( i == 0 )
3450
+ {
3451
+ // Round-trip the source model through a snapshot, compiling it and then extracting it back again.
3452
+ // This simulates the real-world migration flow and can expose errors in snapshot generation
3453
+ // we only do this for the starting model, the subsequent models are just for generating funky migration operations
3454
+ // in the scenario that we want to simulate, those additional models would not have been backed up by the model snapshot
3455
+ // as they either were manually added migration ops, or result of squashing
3456
+ var migrationsCodeGenerator = Fixture . TestHelpers . CreateDesignServiceProvider ( ) . GetRequiredService < IMigrationsCodeGenerator > ( ) ;
3457
+ var sourceModelSnapshot = migrationsCodeGenerator . GenerateSnapshot (
3458
+ modelSnapshotNamespace : null , typeof ( DbContext ) , "MigrationsTestSnapshot" , preSnapshotModel ) ;
3459
+ var sourceModel = BuildModelFromSnapshotSource ( sourceModelSnapshot ) ;
3460
+ models . Add ( sourceModel ) ;
3461
+ preSnapshotSourceModel = preSnapshotModel ;
3462
+ }
3463
+ else
3464
+ {
3465
+ models . Add ( preSnapshotModel ) ;
3466
+ }
3467
+ }
3468
+
3469
+ // build all migration operations going through each intermediate state of the model
3470
+ var operations = new List < MigrationOperation > ( ) ;
3471
+ for ( var i = 0 ; i < models . Count - 1 ; i ++ )
3472
+ {
3473
+ operations . AddRange (
3474
+ modelDiffer . GetDifferences ( models [ i ] . GetRelationalModel ( ) , models [ i + 1 ] . GetRelationalModel ( ) ) ) ;
3475
+ }
3476
+
3477
+ return Test ( preSnapshotSourceModel , models . Last ( ) , operations , asserter , migrationsSqlGenerationOptions ) ;
3478
+ }
3479
+
3308
3480
protected virtual Task Test (
3309
3481
Action < ModelBuilder > buildCommonAction ,
3310
3482
Action < ModelBuilder > buildSourceAction ,
0 commit comments