TFS Release Management を使用して、継続的な統合と展開を行っています。
私は、migrate.exe を使用して展開中にデータベースの移行を実行しています。これは、古いバージョンから新しいバージョンに移行するときにうまく機能します。ただし、アプリケーションの古いバージョンをデプロイする場合は、さらに複雑になります。
基本的に、コンテキストの移行を保持するアセンブリは、たとえばバージョン 3 からバージョン 2 に移行する方法を知っている必要があります。通常、展開しようとしているアセンブリを移行のソースとして使用しますが、この場合は、 v3 から v2 に移行する方法を知っているのは、既に展開されているアセンブリだけであるため、既に展開されているアセンブリを使用します。(バージョン 2 は、v3 が存在することすら知りません。)
私の現在の計画は、展開中に 2 つのアセンブリを何らかの方法で比較することです。インストール ディレクトリのアセンブリに配置ディレクタの移行よりも「新しい」移行が含まれている場合、最初に配置ディレクトリのアセンブリで利用可能な「最新の」移行を取得してから、次のコマンドを実行する必要があります。
migrate.exe AssemblyInInstallationDir /targetMigration NewestFromAssemblyInDeploymentDir
新しいバージョンにアップグレードする「通常の」展開シナリオでは、次のことができます。
migrate.exe AssemblyInDeploymentDir
これは合法的なアプローチですか?各アセンブリで利用可能な移行を評価するために EF ライブラリを使用することについては、まだ調べていません。また、これらのアセンブリのそれぞれが「同じ」でバージョンが異なるだけであるという課題もあります。おそらく、それらを別々のアプリ ドメインにロードしてから、アプリ ドメイン間の通信を使用して必要な情報を取得する必要があります。
編集
同じアセンブリの 2 つの異なるバージョンへの利用可能な移行を一覧表示できる概念実証アプリを作成しました。これはこのプロセス全体にとって非常に重要なので、文書化する価値があると考えました。
アプリはリフレクションを使用して各アセンブリを読み込み、System.Data.Entity.Migrations の DbMigrator クラスを使用して移行メタ データを列挙します。移行の名前にはタイムスタンプ情報がプレフィックスとして付けられているため、それらを注文して、どのアセンブリに「新しい」一連の移行が含まれているかを確認できます。
static void Main(string[] args)
{
const string dllName = "Test.Data.dll";
var assemblyCurrent = Assembly.LoadFile(Path.Combine(System.Environment.CurrentDirectory, string.Format("Current\\{0}", dllName)));
var assemblyTarget = Assembly.LoadFile(Path.Combine(System.Environment.CurrentDirectory, string.Format("Target\\{0}", dllName)));
Console.WriteLine("Curent Version: " + assemblyCurrent.FullName);
Console.WriteLine("Target Version: " + assemblyTarget.FullName);
const string contextName = "Test.Data.TestContext";
const string migrationsNamespace = "Test.Data.Migrations";
var currentContext = assemblyCurrent.CreateInstance(contextName);
var targetContext = assemblyTarget.CreateInstance(contextName);
var currentContextConfig = new DbMigrationsConfiguration
{
MigrationsAssembly = assemblyCurrent,
ContextType = currentContext.GetType(),
MigrationsNamespace = migrationsNamespace
};
var targetContextConfig = new DbMigrationsConfiguration
{
MigrationsAssembly = assemblyTarget,
ContextType = targetContext.GetType(),
MigrationsNamespace = migrationsNamespace
};
var migrator = new DbMigrator(currentContextConfig);
var localMigrations = migrator.GetLocalMigrations(); //all migrations
Console.WriteLine("Current Context Migrations:");
foreach (var m in localMigrations)
{
Console.WriteLine("\t{0}", m);
}
migrator = new DbMigrator(targetContextConfig);
localMigrations = migrator.GetLocalMigrations(); //all migrations
Console.WriteLine("Target Context Migrations:");
foreach (var m in localMigrations)
{
Console.WriteLine("\t{0}", m);
}
Console.ReadKey();
}
}
アプリケーションの出力は次のようになります。
Curent Version: Test.Data, Version=1.3.0.0, Culture=neutral, PublicKeyToken=null
Target Version: Test.Data, Version=1.2.0.0, Culture=neutral, PublicKeyToken=null
Current Context Migrations:
201403171700348_InitalCreate
201403171701519_AddedAddresInfoToCustomer
201403171718277_RemovedStateEntity
201403171754275_MoveAddressInformationIntoContactInfo
201403181559219_NotSureWhatIChanged
201403181731525_AddedRowVersionToDomainObjectBase
Target Context Migrations:
201403171700348_InitalCreate
201403171701519_AddedAddresInfoToCustomer
201403171718277_RemovedStateEntity