Primeras migraciones de EF Code para implementar una versión anterior

Estoy usando TFS Release Management para hacer una integración e implementación continuas.

Estoy usando migrate.exe para realizar la migración de la base de datos durante la implementación, y esto funciona muy bien cuando se pasa de una versión anterior a una nueva. Sin embargo, cuando desea implementar una versión anterior de la aplicación, se vuelve más turbia.

Básicamente, el ensamblaje que contiene sus migraciones para un contexto debe saber cómo pasar de, por ejemplo, la versión 3 a la versión 2. Normalmente, utiliza los ensamblajes que está a punto de implementar como fuente de sus migraciones, pero en este caso, debe use los ensamblajes ya implementados, ya que son los únicos que saben cómo pasar de v3 a v2. (La versión 2 no tiene idea de que v3 incluso existe).

Mi plan actual es comparar de alguna manera los dos ensamblajes durante la implementación. Si el ensamblaje en el directorio de instalación contiene migraciones "más nuevas" que la del director de implementación, primero necesitaría obtener la migración "más nueva" disponible en el ensamblaje en el directorio de implementación y luego ejecutar:

migrate.exe AssemblyInInstallationDir /targetMigration NewestFromAssemblyInDeploymentDir

Donde, como en un escenario de implementación "normal" en el que está actualizando a una versión más nueva, puede hacer lo siguiente:

migrate.exe AssemblyInDeploymentDir

¿Es este un enfoque legítimo? Todavía tengo que estudiar el uso de las bibliotecas EF para evaluar qué migraciones están disponibles en cada ensamblaje. También existe el desafío del hecho de que cada uno de estos conjuntos son las "mismas" versiones diferentes. Probablemente tendré que cargarlos en dominios de aplicación separados y luego usar comunicaciones de dominio entre aplicaciones para obtener la información que necesito.

EDITAR

Creé una aplicación de prueba de concepto que me permite enumerar las migraciones disponibles a dos versiones diferentes del mismo ensamblaje. Esto fue crítico para todo este proceso, así que pensé que valía la pena documentarlo.

La aplicación usa la reflexión para cargar cada uno de los ensamblados y luego usa la clase DbMigrator de System.Data.Entity.Migrations para enumerar los metadatos de migración. Los nombres de las migraciones tienen como prefijo la información de la marca de tiempo, lo que me permite ordenarlos y ver qué ensamblaje contiene el conjunto de migraciones "más nuevo".

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();
}

}

El resultado de la aplicación se ve así:

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

Respuestas a la pregunta(2)

Su respuesta a la pregunta