web-dev-qa-db-ja.com

既存のデータベースを使用したエンティティフレームワークコードの最初の移行戦略

次のような状況で、正しい移行戦略を決定できません。ヘルプはありがたいです。

  • アプリケーションはデータベースを作成し、データストレージとして使用します
  • アプリケーションは起動時にデータベースを更新する必要があります必要な場合
  • Nuget Managerコンソールを使用することはオプションではありません。 (移行の目的で、ローカルでは問題ありません)
  • EFではない既存のデータベースが配布されています

ここで、EFコードファーストアプローチの使用を開始したいと思います。私が達成する必要があるのは:

  1. データベースがない場合は作成します
  2. データベースが存在する場合は、空の移行を使用します(次のアップグレードの準備のためだけに)
  3. これは、アプリケーションの起動時に発生するはずです

データベースが存在しません====> EF初期化を作成=====> Upg v1 =====> Upg V2

データベースが存在します=====>初期をスキップしますが、次のアップグレードの準備ができています=====> Upg v1 ======> Upg v2

ご協力いただきありがとうございます

追加情報:これは存在するデータベースです(単なる例):

CREATE DATABASE Test
GO

Use Test
GO
CREATE SCHEMA [TestSchema] AUTHORIZATION [dbo]
GO
CREATE TABLE [TestSchema].[Table1](
    [Id] [uniqueidentifier] NOT NULL,
    [Column1] [nvarchar](500) NOT NULL,
    [Column2] [bit] NOT NULL,
    [Column3] [bit] NOT NULL,
 CONSTRAINT [PK_MonitorGroups] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

リバースエンジニアリングを使用して、EFは初期移行を作成しました:

public partial class Initial : DbMigration
    {
        public override void Up()
        {
            CreateTable(
                "TestSchema.Table1",
                c => new
                    {
                        Id = c.Guid(nullable: false),
                        Column1 = c.String(nullable: false, maxLength: 500),
                        Column2 = c.Boolean(nullable: false),
                        Column3 = c.Boolean(nullable: false),
                    })
                .PrimaryKey(t => t.Id);
        }

        public override void Down()
        {
            DropTable("TestSchema.Table1");
        }
    }

@spenderが提供するコードを存在しないデータベースに対して使用すると、すべてがクールになります。既存のデータベースに対して使用すると、モデルを変更するまで機能します(次の移行)。

私が見たのは、移行によって返されるアップグレードスクリプトには、データベースの作成全体が含まれているということです。また、既存のオブジェクトに対しては実行できません。

実際に機能するのは、既存のデータベースに移行テーブルを追加して初期データを追加することですが、これが適切なソリューションかどうかはわかりません。

14
Adi

これは私が理解するのにかなりの時間がかかったので、ここでそれを共有できてうれしいです。

したがって、最初にデータベースをリバースエンジニアリングする必要があります。 Entity Frameworkの電動工具 これを行うことができます。インストールしたら、プロジェクトにnugetを使用してEFをインストールし、ソリューションエクスプローラーでプロジェクトノードを右クリックしてから、Entity Framework-> Reverse Engineer Code Firstを選択します。これにより、多数のモデルクラスとマッピングクラスがプロジェクトに生成されます。

次に、パッケージマネージャーコンソールで

Enable-Migrations

その後

Add-Migration Initial

空のDBから現在のスキーマへの移行を説明する移行を作成します。

次に、生成されたConfiguration.csクラスコンストラクターを編集します。

    public Configuration()
    {

        AutomaticMigrationsEnabled = false;
        AutomaticMigrationDataLossAllowed = false;
    }

次に、アプリの起動時に(Webサーバーから実行している場合はglobal.asax Application_Startで)、移行をトリガーする必要があります。このメソッドは仕事をします:

    public static void ApplyDatabaseMigrations()
    {
        //Configuration is the class created by Enable-Migrations
        DbMigrationsConfiguration dbMgConfig = new Configuration()
        {
            //DbContext subclass generated by EF power tools
            ContextType = typeof(MyDbContext)
        };
        using (var databaseContext = new MyDbContext())
        {
            try
            {
                var database = databaseContext.Database;
                var migrationConfiguration = dbMgConfig;
                migrationConfiguration.TargetDatabase =
                    new DbConnectionInfo(database.Connection.ConnectionString,
                                         "System.Data.SqlClient");
                var migrator = new DbMigrator(migrationConfiguration);
                migrator.Update();
            }
            catch (AutomaticDataLossException adle)
            {
                dbMgConfig.AutomaticMigrationDataLossAllowed = true;
                var mg = new DbMigrator(dbMgConfig);
                var scriptor = new MigratorScriptingDecorator(mg);
                string script = scriptor.ScriptUpdate(null, null);
                throw new Exception(adle.Message + " : " + script);
            }
        }
    }

これで、通常どおりさらに移行を追加できます。アプリの実行時に、これらの移行が適用されていない場合は、ApplyDatabaseMigrationsが呼び出されたときに適用されます。

今、あなたはEFコードの最初の折り畳みにいます。それがあなたの質問だと思いますよね?

20
spender