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](/_next/image?url=https%3A%2F%2Fres.cloudinary.com%2Foriolpuig%2Fimage%2Fupload%2Fq_auto%2Cf_auto%2Fforcode.es%2Fgeneric%2Ffortips-entity-framework_qklfmw.webp&w=1920&q=75)
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:
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.