694 lines
24 KiB
C#
694 lines
24 KiB
C#
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||
|
|
||
|
namespace System.Data.Entity.Migrations
|
||
|
{
|
||
|
using System.Data.Entity.Migrations.Design;
|
||
|
using System.Data.Entity.Migrations.History;
|
||
|
using System.Data.Entity.Migrations.Infrastructure;
|
||
|
using System.Data.Entity.Utilities;
|
||
|
using System.IO;
|
||
|
using System.Linq;
|
||
|
using System.Text.RegularExpressions;
|
||
|
using Xunit;
|
||
|
|
||
|
[Variant(DatabaseProvider.SqlClient, ProgrammingLanguage.CSharp)]
|
||
|
[Variant(DatabaseProvider.SqlServerCe, ProgrammingLanguage.CSharp)]
|
||
|
[Variant(DatabaseProvider.SqlClient, ProgrammingLanguage.VB)]
|
||
|
public class BasicMigrationScenarios : DbTestCase
|
||
|
{
|
||
|
[MigrationsTheory]
|
||
|
public void GetHistory_should_return_migrations_list()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
Assert.True(!migrator.GetDatabaseMigrations().Any());
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
Assert.Equal(1, migrator.GetDatabaseMigrations().Count());
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void ScaffoldInitialCreate_should_return_null_when_db_not_initialized()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
var scaffoldedMigration = migrator.ScaffoldInitialCreate("Foo");
|
||
|
|
||
|
Assert.Null(scaffoldedMigration);
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void ScaffoldInitialCreate_should_return_scaffolded_migration_when_db_initialized()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
var initialCreate = new MigrationScaffolder(migrator.Configuration).Scaffold("InitialCreate");
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v1>(scaffoldedMigrations: initialCreate, contextKey: typeof(ShopContext_v1).FullName);
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v1>(contextKey: "NewOne");
|
||
|
|
||
|
var scaffoldedMigration = migrator.ScaffoldInitialCreate("Foo");
|
||
|
|
||
|
Assert.NotNull(scaffoldedMigration);
|
||
|
Assert.NotSame(initialCreate, scaffoldedMigration);
|
||
|
Assert.Equal(initialCreate.MigrationId, scaffoldedMigration.MigrationId);
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void ScaffoldInitialCreate_should_return_scaffolded_migration_when_db_initialized_and_schema_specified()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v5>();
|
||
|
|
||
|
var initialCreate = new MigrationScaffolder(migrator.Configuration).Scaffold("InitialCreate");
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v5>(scaffoldedMigrations: initialCreate, contextKey: typeof(ShopContext_v5).FullName);
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v5>(contextKey: "NewOne");
|
||
|
|
||
|
var scaffoldedMigration = migrator.ScaffoldInitialCreate("Foo");
|
||
|
|
||
|
Assert.NotNull(scaffoldedMigration);
|
||
|
Assert.NotSame(initialCreate, scaffoldedMigration);
|
||
|
Assert.Equal(initialCreate.MigrationId, scaffoldedMigration.MigrationId);
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Generate_should_create_custom_migration_step()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
var generatedMigration = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration");
|
||
|
|
||
|
Assert.NotNull(generatedMigration);
|
||
|
Assert.True(generatedMigration.MigrationId.Contains("Migration"));
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Generate_should_emit_null_source_when_last_migration_was_explicit()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
var generatedMigration = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration1");
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v1>(scaffoldedMigrations: generatedMigration);
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v2>();
|
||
|
|
||
|
generatedMigration = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration2");
|
||
|
|
||
|
Assert.True(
|
||
|
generatedMigration.DesignerCode.Contains("return null")
|
||
|
|| generatedMigration.DesignerCode.Contains("Return Nothing"));
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Generate_should_emit_source_when_last_migration_was_automatic()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v2>();
|
||
|
|
||
|
var generatedMigration = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration2");
|
||
|
|
||
|
Assert.True(
|
||
|
generatedMigration.DesignerCode
|
||
|
.Contains("Resources.GetString(\"Source\")"));
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Update_should_execute_pending_custom_scripts()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
var generatedMigration = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration");
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v1>(
|
||
|
automaticMigrationsEnabled: false,
|
||
|
scaffoldedMigrations: generatedMigration);
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
Assert.True(TableExists("MigrationsCustomers"));
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Generate_when_model_up_to_date_should_create_stub_migration()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
var generatedMigration = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration");
|
||
|
|
||
|
Assert.True(generatedMigration.UserCode.Length > 300);
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Update_blocks_automatic_migration_when_explicit_source_model()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v2>(automaticDataLossEnabled: true);
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
var generatedMigration = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration1");
|
||
|
|
||
|
ResetDatabase();
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
// Fix-up migrationId to come after previous automatic migration
|
||
|
var oldMigrationId = generatedMigration.MigrationId;
|
||
|
var newMigrationId = MigrationAssembly.CreateMigrationId(oldMigrationId.MigrationName());
|
||
|
generatedMigration.MigrationId = newMigrationId;
|
||
|
generatedMigration.DesignerCode = generatedMigration.DesignerCode.Replace(oldMigrationId, newMigrationId);
|
||
|
|
||
|
migrator
|
||
|
= CreateMigrator<ShopContext_v2>(
|
||
|
automaticMigrationsEnabled: false,
|
||
|
automaticDataLossEnabled: false,
|
||
|
scaffoldedMigrations: generatedMigration);
|
||
|
|
||
|
Assert.Throws<AutomaticDataLossException>(() => migrator.Update())
|
||
|
.ValidateMessage("AutomaticDataLoss");
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Update_down_when_target_migration_id_valid_should_migrate_to_target_version_without_timestamp_part()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
var generatedMigration1 = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration1");
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v1>(
|
||
|
automaticMigrationsEnabled: false,
|
||
|
scaffoldedMigrations: generatedMigration1);
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v2>();
|
||
|
|
||
|
var generatedMigration2 = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration2");
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v2>(
|
||
|
automaticMigrationsEnabled: false,
|
||
|
scaffoldedMigrations: new[] { generatedMigration1, generatedMigration2 });
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
Assert.True(TableExists("crm.tbl_customers"));
|
||
|
|
||
|
migrator.Update("Migration1");
|
||
|
|
||
|
Assert.True(TableExists("MigrationsCustomers"));
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Can_specify_target_up_migration_without_timestamp_part()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
var generatedMigration = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration");
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v1>(
|
||
|
automaticMigrationsEnabled: false,
|
||
|
scaffoldedMigrations: generatedMigration);
|
||
|
|
||
|
migrator.Update("Migration");
|
||
|
|
||
|
Assert.True(TableExists("MigrationsCustomers"));
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Update_when_target_migration_id_invalid_should_throw()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
var generatedMigration = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration");
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v1>(
|
||
|
automaticMigrationsEnabled: false,
|
||
|
scaffoldedMigrations: generatedMigration);
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
Assert.Throws<MigrationsException>(() => migrator.Update("balony"))
|
||
|
.ValidateMessage("MigrationNotFound", "balony");
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Update_when_target_migration_id_valid_should_migrate_to_target_version()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
var generatedMigration1 = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration1");
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v2>();
|
||
|
|
||
|
var generatedMigration2 = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration2");
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v2>(
|
||
|
automaticMigrationsEnabled: false,
|
||
|
scaffoldedMigrations: new[] { generatedMigration1, generatedMigration2 });
|
||
|
|
||
|
migrator.Update(generatedMigration1.MigrationId);
|
||
|
|
||
|
Assert.True(TableExists("MigrationsCustomers"));
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Update_down_when_target_migration_id_valid_should_migrate_to_target_version()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
var generatedMigration1 = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration1");
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v1>(
|
||
|
automaticMigrationsEnabled: false,
|
||
|
scaffoldedMigrations: generatedMigration1);
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v2>();
|
||
|
|
||
|
var generatedMigration2 = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration2");
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v2>(
|
||
|
automaticMigrationsEnabled: false,
|
||
|
scaffoldedMigrations: generatedMigration2);
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
var generatedMigration3 = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration3");
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v2>(
|
||
|
automaticMigrationsEnabled: false,
|
||
|
scaffoldedMigrations: new[] { generatedMigration1, generatedMigration2, generatedMigration3 });
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
Assert.True(TableExists("crm.tbl_customers"));
|
||
|
|
||
|
migrator.Update(generatedMigration1.MigrationId);
|
||
|
|
||
|
Assert.True(TableExists("MigrationsCustomers"));
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Update_down_when_automatic_should_migrate_to_target_version()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>(automaticDataLossEnabled: true);
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
Assert.True(TableExists("MigrationsCustomers"));
|
||
|
|
||
|
migrator.Update(DbMigrator.InitialDatabase);
|
||
|
|
||
|
Assert.False(TableExists("MigrationsCustomers"));
|
||
|
|
||
|
Assert.Null(
|
||
|
new HistoryRepository(
|
||
|
ConnectionString, ProviderFactory,
|
||
|
"System.Data.Entity.Migrations.DbMigrationsConfiguration").GetLastModel());
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
Assert.True(TableExists("MigrationsCustomers"));
|
||
|
Assert.NotNull(
|
||
|
new HistoryRepository(
|
||
|
ConnectionString, ProviderFactory,
|
||
|
"System.Data.Entity.Migrations.DbMigrationsConfiguration").GetLastModel());
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Update_down_when_automatic_and_multiple_steps_should_migrate_to_target_version()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var historyRepository = new HistoryRepository(ConnectionString, ProviderFactory, "MyKey");
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>(automaticDataLossEnabled: true);
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
Assert.True(TableExists("MigrationsCustomers"));
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v2>(automaticDataLossEnabled: true);
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
Assert.True(TableExists("crm.tbl_customers"));
|
||
|
|
||
|
migrator.Update(DbMigrator.InitialDatabase);
|
||
|
|
||
|
Assert.False(TableExists("MigrationsCustomers"));
|
||
|
Assert.False(TableExists("tbl_customers"));
|
||
|
Assert.Null(historyRepository.GetLastModel());
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Update_down_when_explicit_should_migrate_to_target_version()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
var generatedMigration = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration1");
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v1>(
|
||
|
automaticMigrationsEnabled: false,
|
||
|
scaffoldedMigrations: generatedMigration);
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
Assert.True(TableExists("MigrationsCustomers"));
|
||
|
|
||
|
migrator.Update(DbMigrator.InitialDatabase);
|
||
|
|
||
|
Assert.False(TableExists("MigrationsCustomers"));
|
||
|
|
||
|
var historyRepository = new HistoryRepository(ConnectionString, ProviderFactory, "MyKey");
|
||
|
|
||
|
Assert.Null(historyRepository.GetLastModel());
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Update_down_when_initial_version_and_no_database_should_be_noop()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
var generatedMigration = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration1");
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v1>(
|
||
|
automaticMigrationsEnabled: false,
|
||
|
scaffoldedMigrations: generatedMigration);
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
Assert.True(TableExists("MigrationsCustomers"));
|
||
|
|
||
|
DropDatabase();
|
||
|
|
||
|
migrator.Update(DbMigrator.InitialDatabase);
|
||
|
|
||
|
Assert.False(migrator.GetDatabaseMigrations().Any());
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Update_down_when_explicit_and_automatic_should_migrate_to_target_version()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var historyRepository = new HistoryRepository(ConnectionString, ProviderFactory, "MyKey");
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
Assert.True(TableExists("MigrationsCustomers"));
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v2>(automaticDataLossEnabled: true);
|
||
|
|
||
|
var generatedMigration = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration");
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v2>(
|
||
|
automaticDataLossEnabled: true,
|
||
|
scaffoldedMigrations: generatedMigration);
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
Assert.True(TableExists("crm.tbl_customers"));
|
||
|
|
||
|
migrator.Update(DbMigrator.InitialDatabase);
|
||
|
|
||
|
Assert.False(TableExists("MigrationsCustomers"));
|
||
|
Assert.False(TableExists("tbl_customers"));
|
||
|
Assert.Null(historyRepository.GetLastModel());
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Generate_when_empty_source_database_should_diff_against_empty_model()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
var generatedMigration = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration");
|
||
|
|
||
|
Assert.Equal(4, Regex.Matches(generatedMigration.UserCode, "CreateTable").Count);
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Can_generate_and_update_against_empty_source_model()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v1>();
|
||
|
|
||
|
var generatedMigration = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration_v1");
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v1>(false, scaffoldedMigrations: generatedMigration);
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
Assert.True(TableExists("MigrationsProducts"));
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Can_generate_against_existing_model()
|
||
|
{
|
||
|
Can_generate_and_update_against_empty_source_model();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v2>();
|
||
|
|
||
|
var generatedMigration = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration_v2");
|
||
|
|
||
|
Assert.Equal(2, Regex.Matches(generatedMigration.UserCode, "RenameTable").Count);
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Can_generate_migration_with_store_side_renames()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
CreateMigrator<ShopContext_v1>().Update();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v2>();
|
||
|
|
||
|
var generatedMigration = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration");
|
||
|
|
||
|
Assert.True(generatedMigration.UserCode.Contains("RenameTable"));
|
||
|
WhenNotSqlCe(() => Assert.True(generatedMigration.UserCode.Contains("RenameColumn")));
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Can_update_generate_update_when_empty_target_database()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
CreateMigrator<ShopContext_v1>().Update();
|
||
|
|
||
|
Assert.True(TableExists("MigrationsProducts"));
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v2>();
|
||
|
|
||
|
var generatedMigration = new MigrationScaffolder(migrator.Configuration).Scaffold("Migration");
|
||
|
|
||
|
migrator = CreateMigrator<ShopContext_v2>(false, scaffoldedMigrations: generatedMigration);
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
Assert.True(TableExists("crm.tbl_customers"));
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Can_auto_update_v1_when_target_database_does_not_exist()
|
||
|
{
|
||
|
var migrator = CreateMigrator<ShopContext_v1>(targetDatabase: Path.GetRandomFileName());
|
||
|
|
||
|
try
|
||
|
{
|
||
|
migrator.Update();
|
||
|
|
||
|
Assert.True(TableExists("MigrationsProducts"));
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
DropDatabase();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Update_throws_on_automatic_data_loss()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
CreateMigrator<NonEmptyModel>().Update();
|
||
|
|
||
|
var migrator = CreateMigrator<EmptyModel>();
|
||
|
|
||
|
Assert.Equal(
|
||
|
new AutomaticDataLossException("Automatic migration was not applied because it would result in data loss.").Message,
|
||
|
Assert.Throws<AutomaticDataLossException>(() => migrator.Update()).Message);
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Update_can_process_automatic_data_loss()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
CreateMigrator<NonEmptyModel>().Update();
|
||
|
|
||
|
var migrator = CreateMigrator<EmptyModel>(automaticDataLossEnabled: true);
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
Assert.False(TableExists("MigrationsBlogs"));
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Can_update_multiple_migrations_having_a_trailing_automatic_migration()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
CreateMigrator<ShopContext_v1>().Update();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v2>();
|
||
|
|
||
|
var generatedMigration = new MigrationScaffolder(migrator.Configuration).Scaffold("Version 2");
|
||
|
|
||
|
ResetDatabase();
|
||
|
|
||
|
CreateMigrator<ShopContext_v3>(scaffoldedMigrations: generatedMigration).Update();
|
||
|
|
||
|
Assert.True(TableExists("MigrationsStores"));
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Can_downgrade_with_leading_automatic_when_database_empty()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
CreateMigrator<ShopContext_v1>().Update();
|
||
|
|
||
|
var migrator = CreateMigrator<ShopContext_v2>();
|
||
|
|
||
|
var scaffoldedMigration
|
||
|
= new MigrationScaffolder(migrator.Configuration).Scaffold("Migration");
|
||
|
|
||
|
migrator
|
||
|
= CreateMigrator<ShopContext_v2>(
|
||
|
scaffoldedMigrations: scaffoldedMigration,
|
||
|
automaticDataLossEnabled: true);
|
||
|
|
||
|
ResetDatabase();
|
||
|
|
||
|
migrator.Update();
|
||
|
|
||
|
Assert.True(TableExists("OrderLines"));
|
||
|
|
||
|
migrator.Update("0");
|
||
|
|
||
|
Assert.False(TableExists("OrderLines"));
|
||
|
}
|
||
|
|
||
|
[MigrationsTheory]
|
||
|
public void Update_when_new_earlier_migration_should_throw_auto_disabled_exception()
|
||
|
{
|
||
|
ResetDatabase();
|
||
|
|
||
|
var migratorA = CreateMigrator<MultiUserContextA>();
|
||
|
var m1 = new MigrationScaffolder(migratorA.Configuration).Scaffold("M1");
|
||
|
|
||
|
var migratorB = CreateMigrator<MultiUserContextB>();
|
||
|
var m2 = new MigrationScaffolder(migratorB.Configuration).Scaffold("M2");
|
||
|
|
||
|
CreateMigrator<MultiUserContextB>(scaffoldedMigrations: m2).Update();
|
||
|
|
||
|
Assert.Throws<AutomaticMigrationsDisabledException>(
|
||
|
() => CreateMigrator<MultiUserContextAB>(
|
||
|
scaffoldedMigrations: new[] { m1, m2 },
|
||
|
automaticMigrationsEnabled: false)
|
||
|
.Update());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class MultiUserContextA : DbContext
|
||
|
{
|
||
|
public DbSet<MultiUserA> As { get; set; }
|
||
|
}
|
||
|
|
||
|
public class MultiUserContextB : DbContext
|
||
|
{
|
||
|
public DbSet<MultiUserB> Bs { get; set; }
|
||
|
}
|
||
|
|
||
|
public class MultiUserContextAB : DbContext
|
||
|
{
|
||
|
public DbSet<MultiUserA> As { get; set; }
|
||
|
public DbSet<MultiUserB> Bs { get; set; }
|
||
|
}
|
||
|
|
||
|
public class MultiUserA
|
||
|
{
|
||
|
public int Id { get; set; }
|
||
|
}
|
||
|
|
||
|
public class MultiUserB
|
||
|
{
|
||
|
public int Id { get; set; }
|
||
|
}
|
||
|
}
|