2016-03-17 7 views
5

新しいコンテキストに切り替えた後、EntityFrameworkの移行が無意味になります。 DbMigratorは、最初のデータベースインスタンスからの保留中の移行の一覧を使用しています。これは、他のデータベースに移行が適用されないことを意味します。データベースの切り替え後にDbMigratorが保留中の移行を検出しない

  • EF 6
  • MS SQL Serverの2014年、同じデータベースモデルの複数のインスタンスを持つC#.NET 4.5 MVCプロジェクト。
  • マイグレーションによるCodeFirstアプローチ。
  • DbContext初期化子がnullに設定されています。

アプリケーションの開始データベースを作成および更新するためのカスタムDb初期化があります。 CreateDatabaseIfNotExistsが意図したとおりに動作している場合、新しいデータベースにはすべての移行が適用されます。しかし、MigrateDatabaseToLatestVersionイニシャライザと私たちのカスタムイニシャライザの両方が、リストの最初のもの以外のデータベースを更新することに失敗しています。正しく動作context.Database.CreateIfNotExists();

foreach (var connectionString in connectionStrings) 
{ 
    using (var context = new ApplicationDbContext(connectionString)) 
    { 
     //Create database 
     var created = context.Database.CreateIfNotExists(); 

     var conf = new Workshop.Migrations.Configuration(); 
     var migrator = new DbMigrator(conf); 

     migrator.Update(); 

     //initial values 
     conf.RunSeed(context); 
    } 
} 
  • migrator.GetLocalMigrations()は常に正しい値を返します。
  • migrator.GetPendingMigrations()最初のデータベースが空のリスト を返した後。
  • migrator.GetDatabaseMigrations()は、空のデータベースのフルリストイベントを含む最初のデータベースの後に、保留中の移行のミラーです。
  • Dbインスタンスからデータ(context.xxx.ToList())を取得すると、接続が正常に動作していることを確認し、正しいインスタンスにリンクします。

最新の移行への更新を強制的にmigrator.Update("migration_name");に変更すると、何も変わりません。私がEFのソースコードを読んで収集したものから、保留中のマイグレーションリストがそれ自身でチェックされ、結果が間違っています。

キャッシングがボンネットの下にあるようですが、リセットする方法がわかりません。

複数のデータベースで移行を実行する方法はありますか、EFではもう1つの「設計上のバグ」ですか?


編集:

本当の問題は、それ自身の使用のための新しいコンテキストを作成DbMigratorです。それは私のケースではデフォルトの(最初の)接続文字列web.Configにフォールバックしていたデフォルトのパラメータのないコンストラクタを介して行います。

私は、この問題のために良い解決策が表示されませんが、私の場合は原始的な回避策は一時的にデフォルトの接続文字列を編集することです:私はまだ誰かが願っていますHow do I set a connection string config programatically in .net?


:から

var originalConStr = WebConfigurationManager.ConnectionStrings["ApplicationDbContext"].ConnectionString; 

var setting = WebConfigurationManager.ConnectionStrings["ApplicationDbContext"]; 

var fi = typeof(ConfigurationElement).GetField("_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic); 

//disable readonly flag on field 
fi.SetValue(setting, false); 

setting.ConnectionString = temporaryConnectionString; //now it works 

//DO STUFF 

setting.ConnectionString = originalConStr; //revert changes 

チートを本当の解決策を見いだしてください。今私は自己解答を控えるでしょう。

答えて

4

DbMigrationsConfiguration.TargetDatabaseプロパティを正しく設定する必要があります。そうしないと、移行プログラムは既定の接続情報を使用します。

だから、理論的には、あなたは残念ながら、この

conf.TargetDatabase = new System.Data.Entity.Infrastructure.DbConnectionInfo(...); 

DbConnectionInfoの唯一の2公共constructorsような何かをしている行うことができます

connectionNameの

public DbConnectionInfo(string connectionName) 
:接続文字列の名前でアプリケーション構成。接続に使用する接続文字列:をのConnectionString

public DbConnectionInfo(string connectionString, string providerInvariantName) 


providerInvariantName:接続に使用するプロバイダの名前。 SQL Serverには 'System.Data.SqlClient'を使用します。

接続文字列が表示されていますが、どうすればproviderInvariantNameを入手できるか分かりません。

UPDATE:私は必要な情報を取るのは良い「公式」の道を見つけることができませんでしたので、私はリフレクション経由internalメンバーへのアクセスにハックを使用して終了しましたが、まだIMOそれは何よりもかなり多くの方が安全ですあなたが使用している:

var internalContext = context.GetType().GetProperty("InternalContext", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(context); 
var providerName = (string)internalContext.GetType().GetProperty("ProviderName").GetValue(internalContext); 
var conf = new Workshop.Migrations.Configuration(); 
conf.TargetDatabase = new System.Data.Entity.Infrastructure.DbConnectionInfo(connectionString, providerName); 
+0

をうーん... DbContextConfigurationはとても実用的なアプローチは、ここで失敗する(DbMigratorコンストラクタがそれを望んでいる)DbMigrationsConfigurationとして動作するように望んでいません。 DbMigratorがそれを無視し、デフォルトでweb.configからの接続文字列を使用する私のContextのパラメータのないコンストラクタを呼び出すため、カスタム接続情報が失敗します。 (これは私の本当の問題です、それが表示されます)。最後に、更新の間リフレクションによって 'ebConfigurationManager.ConnectionStrings [" ApplicationDbContext "]'を編集するだけです。私はそこに良い方法があることを望む(シングルトン/静的フィールドが良く聞こえない)。 – PTwr

+0

おっと、あなたは血まみれです! –

+0

いいえ、私はそうではありません。私のチームリーダーは; – PTwr

関連する問題