public static Task MigrateAsync(this DbContext v, string migration = "") { if (string.IsNullOrEmpty(migration)) { return(v.Database.MigrateAsync()); } else { IMigrator migrator = v.GetInfrastructure().GetService <IMigrator>(); return(migrator.MigrateAsync(migration)); } }
public async Task GivenTheCurrentMigrations_WhenRunningThemInBothDirections_DatabaseIsCorrectlyMigrated() { // Arrange string databaseName = $"it--{nameof(GivenTheCurrentMigrations_WhenRunningThemInBothDirections_DatabaseIsCorrectlyMigrated)}"; DbContextOptions <TodoDbContext> dbContextOptions = GetDbContextOptions(databaseName); await using TodoDbContext todoDbContext = new TodoDbContext(dbContextOptions); bool isMigrationSuccessful; try { await todoDbContext.Database.EnsureDeletedAsync(); IMigrator databaseMigrator = todoDbContext.GetInfrastructure().GetRequiredService <IMigrator>(); // Act await databaseMigrator.MigrateAsync(); // Revert migrations by using a special migration identifier. // See more here: https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/dotnet#dotnet-ef-database-update. await databaseMigrator.MigrateAsync(BeforeFirstDatabaseMigration); await databaseMigrator.MigrateAsync(); isMigrationSuccessful = true; } catch { isMigrationSuccessful = false; } finally { await todoDbContext.Database.EnsureDeletedAsync(); } // Assert isMigrationSuccessful.Should().BeTrue("migrations should work in both directions, up and down"); }
/// <summary> /// Applies pending migrations, if any. /// </summary> /// <param name="ep">The IEndPointConfiguration whose properties will be used as keys.</param> /// <returns>A list of names of migrations that were applied.</returns> public virtual async Task <List <string> > ApplyMigrations(IEndPointConfiguration endPoint) { DbContext context = resolver.ResolveMigrationContext(endPoint); IDatabaseInitializer dataInitializer = resolver.ResolveDatabaseInitializer(endPoint); List <string> migrations = (await context.Database.GetPendingMigrationsAsync()).ToList(); IMigrator migrator = context.Database.GetService <IMigrator>(); foreach (string migrationName in migrations) { await migrator.MigrateAsync(migrationName); if (dataInitializer != null) { await dataInitializer.Seed(migrationName); } } return(migrations); }
public async Task SaveChanges_WhenModifyingSameEntityUsingTwoConcurrentTransactions_ThrowsException() { // Arrange string databaseName = $"it--{nameof(SaveChanges_WhenModifyingSameEntityUsingTwoConcurrentTransactions_ThrowsException)}"; DbContextOptions <TodoDbContext> dbContextOptions = GetDbContextOptions(databaseName); await using TodoDbContext firstTodoDbContext = new TodoDbContext(dbContextOptions); IMigrator databaseMigrator = firstTodoDbContext.GetInfrastructure().GetRequiredService <IMigrator>(); await databaseMigrator.MigrateAsync(); try { string name = "ConcurrentlyAccessedTodoItem"; TodoItem todoItem = new TodoItem(name, "it") { IsComplete = false, }; await firstTodoDbContext.TodoItems.AddAsync(todoItem); await firstTodoDbContext.SaveChangesAsync(); await using IDbContextTransaction firstTransaction = await firstTodoDbContext.Database.BeginTransactionAsync(); TodoItem todoItemFromFirstTransaction = await firstTodoDbContext.TodoItems.FirstAsync(x => x.Name == name); todoItemFromFirstTransaction.IsComplete = true; todoItemFromFirstTransaction.LastUpdatedBy = Guid.NewGuid().ToString("N"); todoItemFromFirstTransaction.LastUpdatedOn = DateTime.UtcNow; await using TodoDbContext secondTodoDbContext = new TodoDbContext(dbContextOptions); await using IDbContextTransaction secondTransaction = await secondTodoDbContext.Database.BeginTransactionAsync(); TodoItem todoItemFromSecondTransaction = await secondTodoDbContext.TodoItems.FirstAsync(x => x.Name == name); todoItemFromSecondTransaction.IsComplete = false; todoItemFromSecondTransaction.LastUpdatedBy = Guid.NewGuid().ToString("N"); todoItemFromSecondTransaction.LastUpdatedOn = DateTime.UtcNow; await firstTodoDbContext.SaveChangesAsync(); await firstTransaction.CommitAsync(); // Act Func <Task> saveChangesAsyncCall = async() => { // ReSharper disable AccessToDisposedClosure await secondTodoDbContext.SaveChangesAsync(); await secondTransaction.CommitAsync(); // ReSharper restore AccessToDisposedClosure }; // Assert saveChangesAsyncCall.Should() .ThrowExactly <DbUpdateConcurrencyException>( "2 transactions were concurrently modifying the same entity"); } finally { await firstTodoDbContext.Database.EnsureDeletedAsync(); } }
public async Task <MigratorHarness <TContext> > TargetMigrationAsync(string migrationName) { await _migrator.MigrateAsync(migrationName); return(this); }