Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

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; }
}
}