21

複数のコードファースト DbContext で EF 4.3 移行を使用しようとしています。私のアプリケーションはいくつかのプラグインに分かれており、ドメインに関して独自の DbContext を持つ可能性があります。アプリケーションは、単一の sql-database を使用する必要があります。

空のデータベースでコンテキストを自動移行しようとすると、最初のコンテキストでのみ成功します。他のすべてのコンテキストでは、AutomaticMigrationDataLossAllowed-Property を true に設定する必要がありますが、前のテーブルの削除を試みます。

だから私の質問は:

  • 対応するコンテキストで定義されたテーブルの世話をし、他のすべてをそのままにしておくように移行構成に指示するにはどうすればよいですか?
  • 単一のデータベースで自動移行を使用して複数の DbContext を処理するための適切なワークフローは何ですか?

ありがとうございました!

4

9 に答える 9

32

これがあなたができることです。とても簡単です。

コンテキストごとに構成クラスを作成できます。例えば

internal sealed class Configuration1 : DbMigrationsConfiguration<Context1>{
   public Configuration1 (){
        AutomaticMigrationsEnabled = false;
        MigrationsNamespace = "YourProject.Models.ContextNamespace1";
   }
}

internal sealed class Configuration2 : DbMigrationsConfiguration<Context2>{
   public Configuration2 (){
        AutomaticMigrationsEnabled = false;
        MigrationsNamespace = "YourProject.Models.ContextNamespace2";
   }
}

次に、移行を追加します。上記の 2 つのクラスで既に行っているため、移行を有効にする必要はありません。

Add-Migration -configuration Configuration1 Context1Init

これにより、context1 の移行スクリプトが作成されます。他のコンテキストに対してこれを繰り返すことができます。

Add-Migration -configuration Configuration2 Context2Init

データベースを更新するには

Update-Database -configuration Configuration1
Update-Database -configuration Configuration2

これは任意の順序で実行できます。ただし、各構成が順番に呼び出されるようにする必要があります。

于 2012-04-04T10:40:06.077 に答える
6

Code First Migrations は、データベースごとに 1 つの移行構成 (および構成ごとに 1 つのコンテキスト) のみがあることを前提としています。

考えられる解決策は次の 2 つです。

  1. 各コンテキストのすべてのエンティティを含む集約コンテキストを作成し、移行構成クラスからこの「スーパー」コンテキストを参照します。この方法では、すべてのテーブルがユーザーのデータベースに作成されますが、データはプラグインをインストールしたテーブルにのみ存在します。

  2. コンテキストごとに個別のデータベースを使用します。コンテキスト間でエンティティを共有している場合は、カスタム マイグレーションを追加し、呼び出しを、エンティティの「元の」データベースからデータを取得するためのCreateTable(...)呼び出しに置き換えます。Sql("CREATE VIEW ...")

すべてを単一のデータベースに保持するため、#1 を試してみます。ソリューションに別のプロジェクトを作成して、移行とこの「スーパー」コンテキストを含めることができます。プロジェクトを追加し、すべてのプラグインのプロジェクトを参照し、すべてのエンティティを含むコンテキストを作成してから、この新しいプロジェクトで Enable-Migrations を呼び出します。その後、物事は期待どおりに機能するはずです。

于 2012-02-10T20:36:32.773 に答える
3

移行を使用して複数のコンテキストを持つ作業サイトがあります。ただし、コンテキストごとに個別のデータベースを使用する必要があり、すべてプロジェクトの Migrations 名前空間の *Configuration クラスから駆動されるため、たとえば、CompanyDbContext は CompanyConfiguration を使用して Company.sdf を指します。update-database -configurationtypename CompanyConfiguration. 別の LogDbContext は、LogConfiguration などを使用して Log.sdf を指します。

これが機能する場合、同じデータベースを指す 2 つのコンテキストを作成し、モデルビルダーに他のコンテキストのテーブルのリストを無視するように指示してみましたか?

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Ignore<OtherContextsClass>();
    // more of these
}

移行は ModelBuilder で機能するため、これでうまくいく可能性があります。

くだらない代替手段は、自動移行の使用を避け、毎回移行を生成し、手動で不要なステートメントを選別して削除してから実行することですが、コンテキストと生成されたステートメントを調べて実行する単純なツールを作成することを妨げるものは何もありませんあなたのための移行修正。

于 2012-02-23T22:52:17.920 に答える
1

わかりました、私はこれに1日苦労してきました。ここに答えを求める人のための解決策があります...

多くの DbSet<> プロパティを持つ大きな DbContext クラスがあり、読み込みに時間がかかるため、この投稿を読んでいるほとんどの人がここにいると思います。一度にすべての dbset を使用するわけではなく、必要な状況に基づいて「部分的な」コンテキストのみをロードするため、コンテキストを分割する必要があると考えたことでしょう。それ。したがって、それらを分割すると、Code First の移行が革命的な考え方をサポートしていないことがわかります。

したがって、最初のステップはコンテキストを分割することだったに違いありません。次に、新しいコンテキストごとに MigrationConfiguration クラスを追加し、新しい Context クラスとまったく同じ名前の接続文字列を追加しました。

次に、Add-Migration Context1 を実行してから Update-Database -Verbose... を実行して、新しく分割されたコンテキストを 1 つずつ実行しようとしました。

すべてが正常に機能しているように見えましたが、その後のすべての移行で、前回の移行からすべてのテーブルが削除され、最後の移行からのテーブルのみが残っていることに気付きました。

これは、現在の移行モデルがデータベースごとに単一の DbContext を想定しており、ミラー マッチである必要があるためです。

私が試したこと、そして誰かがここでそれを提案したことは、すべての Db セットを含む単一の SuperContext を作成することです。単一の移行構成クラスを作成し、それを実行します。部分的な Context クラスをそのままにして、インスタンス化して使用してみてください。EF は、バッキング モデルが変更されたと不平を言っています。繰り返しますが、これは、EF が部分的な dbcontext を、スーパー コンテキストの移行で残された All-Sets コンテキスト シグネチャと比較するためです。

これは私の意見では大きな欠陥です。

私の場合、移行よりもパフォーマンスの方が重要であると判断しました。だから、私がやったのは、スーパーコンテキストで実行してすべてのテーブルを配置した後、データベースに入り、_MigrationHistory テーブルを手動で削除したことです。

これで、EF から文句を言われることなく、部分コンテキストをインスタンス化して使用できるようになりました。MigrationHistory テーブルが見つからず、先に進むだけなので、データベースの「部分的な」ビューを表示できます。

もちろんトレードオフは、モデルへの変更を手動でデータベースに反映する必要があることです。そのため、注意が必要です。

それは私のために働いた。

于 2012-05-27T03:19:22.123 に答える
1

私はちょうどこの問題に遭遇し、それらを異なるコンテキストに分割した理由は、純粋に関連するモデルを扱いやすいチャンクにグループ化するためであり、他の技術的な理由ではないことに気付きました。代わりに、コンテキストを部分クラスとして宣言し、さまざまなモデルを含むさまざまなコード ファイルで DbSet を DbContext に追加できるようになりました。

このようにして、自動移行の魔法は引き続き機能します。

于 2013-01-08T16:22:09.007 に答える
1

ブライスが上で述べたように、最も実用的な解決策は、アプリケーション/データベースごとに 1 つのスーパー DbContext を持つことです。

アプリケーション全体で 1 つの DbContext のみを使用する必要があることは、技術的にも方法論的にも重大な欠点と思われます。これは、特にモジュール性に影響を与えるためです。また、WCF Data Services を使用している場合、DataService は 1 つの DbContext にのみマップできるため、アプリケーションごとに 1 つの DataService しか使用できません。したがって、これによりアーキテクチャが大幅に変更されます。

プラス面としては、データベース関連のすべての移行コードが一元化されているという小さな利点があります。

于 2012-11-10T02:20:54.327 に答える
0

確かに、解決策は、独立したDbContextエンティティの変更を処理できるように、_MigrationHistoryテーブルを_MigrationHistory_Context1のような選択したテーブル名に直接変更できるようにAPIを変更するためのEntityFrameworkチームによる変更である必要があります。そうすれば、それらはすべて別々に扱われ、エンティティの名前が衝突しないようにするのは開発者次第です。

エンティティのスーパーセットを参照する重複したDbContextは、企業にやさしい偽の方法であるという私の意見を共有する人がたくさんいるようです。重複するDbContextは、モジュラー(Prismまたは同様の)ベースのソリューションでは惨めに失敗します。

于 2012-10-17T09:23:32.103 に答える
0

手動移行で動作しますが、__ MigrationHistoryテーブルの構成を区別できないため、ダウングレードすることはできません。ダウングレードしようとすると、他の構成からの移行が自動として扱われ、データの損失を許可しないため失敗します。ただし、アップグレードにのみ使用するため、目的に応じて機能します。

DbContextの間に重複がなければ、それをサポートするのは難しいことではないと確信しています。

于 2012-05-03T09:13:57.490 に答える
0

以下のこの答えが私にとってうまくいったことを人々に知ってもらいたいのですが、1つの注意点があります: MigrationsNamespace 行を使用しないでください。

internal sealed class Configuration1 : DbMigrationsConfiguration<Context1>{
       public Configuration1 (){
        AutomaticMigrationsEnabled = false;
        MigrationsNamespace = "YourProject.Models.ContextNamespace1";
   }
 }

internal sealed class Configuration2 : DbMigrationsConfiguration<Context2>{
   public Configuration2 (){
        AutomaticMigrationsEnabled = false;
        MigrationsNamespace = "YourProject.Models.ContextNamespace2";
   }
}

ただし、独自のコンテキストが定義された 2 つのデータベースが既に確立されているため、「YourProject.Models 名前空間には ContextNamespace1 が既に定義されています」というエラーが表示されることに気付きました。これは、「MigrationsNamespace = "YourProject.Models.ContextNamespace2";」が原因でした。Initを試した後、2回(移行Context1Initファイルで1回、以前に定義した場所で1回)、YourProjects.Models名前空間でdbcontextが定義されていました。

したがって、その時点で私がしなければならなかったことは、次の指示に従って、データベースと移行を最初から開始することであることがわかりました (ありがたいことに、保持する必要のあるデータがありませんでした) 。 -framework-reseting-migrations/

次に、コードを変更して MigrationsNamespace 行を含めないようにしました。

internal sealed class Configuration1 : DbMigrationsConfiguration<Context1>{
       public Configuration1 (){
        AutomaticMigrationsEnabled = false;
   }
 }

internal sealed class Configuration2 : DbMigrationsConfiguration<Context2>{
   public Configuration2 (){
        AutomaticMigrationsEnabled = false;
   }
}

次に、 Add-Migration -configuration Configuration1 Context1Init コマンドを再度実行し、 Update-Database -configuration Configuration1 行を再度実行しました (2 番目のコンテキストについても)。最終的に、すべてがうまく機能しているようです。

于 2013-11-29T03:27:46.437 に答える