Entity Framework: Ejecución de Scripts

[forTips] Entity Framework

Si trabajáis con Entity Framework Code First, sabréis que los cambios de esquema los realiza bastante bien pero hay momentos en que necesitamos aplicar scripts para migrar datos u otros propósitos.

Veamos como

Lo primero que intentamos siempre es realizar nuestro propio parseador de ficheros para realizar la tarea que queremos. Y así fue :)

Aunque trás algun error y sin poder depurar mucho la migration de pruebas, realizando una búsqueda encontramos una solución muy parecida a la que queriamos. Y trás acceder al código en github y realizar unas modificaciones quedo esto:

public abstract class DbMigrationExtended : DbMigration
    {
        public void SqlFile(string fileName, bool suppressTransaction = false)
        {
            var cleanAppDir = new Regex(@"\\bin.+");
            var dir = AppDomain.CurrentDomain.BaseDirectory;
            dir = cleanAppDir.Replace(dir, string.Empty);
            var sqlLines = File.ReadAllLines(Path.Combine(dir, string.Format("Scripts/{0}.sql", fileName)));

            var ignore = new[]
			{
				"GO",	// Migrations doesn't support GO
				"/*",	// Migrations might not support comments
				"--",	// Migrations might not support comments
				"print"	// Migrations might not support print
			};

            var sql = string.Join(" ", sqlLines.Where(line => !string.IsNullOrEmpty(line) && !ignore.Any(line.StartsWith)));

            Sql(sql, suppressTransaction);
        }
    }
Adaptaciones Propias

Como podéis ver la complejidad es obtener el directorio de ejecución en el momento de lanzar el update-database desde la consola, además de ignorar ciertas lineas e instrucciones sql por seguridad.
Además hemos realizado una modificación para que por convención nuestros scripts siempre estén ubicadas en una misma carpeta y tengan la misma extensión, en caso contrario fallará; pero nos viene bien para ir cogiendo buenas prácticas de forma que nuestro proyecto tendría esta estructura:

Context project

Al final podemos construir una migration lanzando el típico add-migration en la consola y una vez creada heredar de nuestra nueva clase, si es necesario, y agregar la nueva instrucción para invocar ficheros.

Migration de Ejemplo
public partial class SampleMigration : DbMigrationExtended
    {
        public override void Up()
        {
            SqlFile("MySqlFileNameWithoutExtension");
        }

        public override void Down()
        {

        }
    }

Conclusiones

Si se te ocurre alguna funcionalidad que no provee por defecto .NET, buscalo antes de realizar tu propia funcionalidad, puesto que seguro que antes se le ha ocurrido ya a alguien, hay versiones mejores que la tuya o por lo menos más probadas.