[forCode]

Entity Framework: Ejecución de Scripts

Si has usado Entity Framwork Code First, sabrás que hay momentos en que necesitamos lanar scripts externos de SQL. Veamos algún ejemplo en concreto.

Entity Framework: Ejecución de Scripts

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:

Pantallazo de la estructura de carpetas del proyecto

Pantallazo de la estructura de carpetas del proyecto

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.

Compartir en: