sql >> データベース >  >> RDS >> Mysql

mysqlデータベースを作成および移行するための初期化子を作成するにはどうすればよいですか?

    私はあなたがほとんどそこにいると思います-あなたはMigrateDatabaseToLatestVersionのソースコードを検索することができます (オープンソースの http://entityframework.codeplex.com/ )-かなり単純化されています。ほとんどの場合、DbMigratorと呼ばれます。 -私が見る限り。

    あなたがしなければならないのは、2つをマージすることです-どちらか一方をベースとして使用し、そこに他の機能を追加します-それはうまくいくはずです。

    class CreateAndMigrateDatabaseInitializer<TContext, TConfiguration> : CreateDatabaseIfNotExists<TContext>, IDatabaseInitializer<TContext> 
        where TContext : DbContext
        where TConfiguration : DbMigrationsConfiguration<TContext>, new()
    {
        private readonly DbMigrationsConfiguration _configuration;
        public CreateAndMigrateDatabaseInitializer()
        {
            _configuration = new TConfiguration();
        }
        public CreateAndMigrateDatabaseInitializer(string connection)
        {
            Contract.Requires(!string.IsNullOrEmpty(connection), "connection");
    
            _configuration = new TConfiguration
            {
                TargetDatabase = new DbConnectionInfo(connection)
            };
        }
        void IDatabaseInitializer<TContext>.InitializeDatabase(TContext context)
        {
            Contract.Requires(context != null, "context");
    
            var migrator = new DbMigrator(_configuration);
            migrator.Update();
    
            // move on with the 'CreateDatabaseIfNotExists' for the 'Seed'
            base.InitializeDatabase(context);
        }
        protected override void Seed(TContext context)
        {
        }
    }
    

    このように呼んでください...

    Database.SetInitializer(new CreateAndMigrateDatabaseInitializer<GumpDatabase, YourNamespace.Migrations.Configuration>());
    

    ...実際には、CreateDatabaseIfNotExistsの場合と同じように、(一般的な実装であるため)オーバーライドします。 (構成用に追加の「param」があります)-そして「シード」を指定するだけです。

    class GumpDatabaseInitializer : CreateAndMigrateDatabaseInitializer<GumpDatabase, YourNamespace.Migrations.Configuration>
    {
        protected override void Seed(GumpDatabase context)
        {
            context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX Name ON Stations (Name)");
        }
    }
    

    ...そしてそれを

    のようなものと呼びます
    Database.SetInitializer(new GumpDatabaseInitializer());
    

    編集: コメントに基づく-DbMigratorは2回実行しないでください。常にチェックし(少し時間を費やし)、「空白」の更新を実行して次に進みます。ただし、それを削除して入力する前に「チェック」したい場合に備えて、これは機能するはずです(上記の同様の部分を変更してください)...

    var migrator = new DbMigrator(_configuration);
    if (!context.Database.CompatibleWithModel(throwIfNoMetadata: false))
        if (migrator.GetPendingMigrations().Any())
            migrator.Update();
    

    (これは冗長/ダブルチェックです-if-sの1つで十分です。そこに休憩を入れて-Dbが移行されたら、何が起こっているのかを正確に確認してください-入らないようにしてください。前述のように、私がテストしてください。

    編集:

    InitializeDatabaseの内部を置き換えます と...

    var doseed = !context.Database.Exists();
    // && new DatabaseTableChecker().AnyModelTableExists(context);
    // check to see if to seed - we 'lack' the 'AnyModelTableExists' - could be copied/done otherwise if needed...
    
    var migrator = new DbMigrator(_configuration);
    // if (doseed || !context.Database.CompatibleWithModel(throwIfNoMetadata: false))
        if (migrator.GetPendingMigrations().Any())
            migrator.Update();
    
    // move on with the 'CreateDatabaseIfNotExists' for the 'Seed'
    base.InitializeDatabase(context);
    if (doseed)
    {
        Seed(context);
        context.SaveChanges();
    }
    

    これは、(途中で)シードされないことを回避します-移行が最初に行われる場合。そして、移行を最初に行う必要があります。そうしないと、問題が発生します。

    あなたはまだそれを適切に行う必要があります-これはあなたが必要とするかもしれないすべてではないにしても要点です-しかしMySQLなどで問題があれば、おそらくここでもう少し足がかりです。

    注: それでも、dbがある場合はシードは呼び出されませんが、空です。問題は、2つの異なる初期化子の混合です。したがって、Create ...が内部で行うこと(呼び出すことはできません)または他の何かを実装することによって、それを解決する必要があります。



    1. MariaDB JSON_REPLACE()の説明

    2. Oracleでクエリ結果をコンマ区切りリストとして返す

    3. Linux上の.NETをODBCデータソースに接続する

    4. ODP.NET接続プーリング:接続が使用されたかどうかを確認する方法