La .NET CONF 2024 acaba de terminar. Descubre las NOVEDADES de .NET 9 junto a los CAMBIOS que trae C# 13.
Puedes ver el contenido de este vídeo junto con su curso en el modo vídeo (similar a Udemy) si pulsas aquí.

Migraciones en Entity Framework Core de manera efectiva

En el post anterior vimos que es code first en entity framework core, pero en ese post, solo vimos la punta del iceberg, una pequeña explicación al funcionamiento del mismo. En este post, vamos a ver como el 99.9% de las empresas implementan code first. Utilizando migrations.

 

 

1 - Qué son las migraciones en Entity framework Core?

Las migraciones o migrations en Entity Framework core son la forma de mantener la estructura del modelo que estás utilizando en tu aplicación sincronizada con la base de datos. En otras palabras, te permiten ir actualizando tu código y que la base de datos se vaya actualizando acordemente. 

Y esto Entity Framework lo permite hacer de una forma muy sencilla. 

 

Para este post, vamos a utilizar el código que está en GitHub que ya vimos en el post anterior. 

 

 

2 - Implementar migraciones en Entity Framework Core

como en otros posts vamos a empezar de cero. Lo único que tenemos por ahora son las entidades así como el DbContex que como sabes representan la estrucura de nuestra base de datos:

public class Wokringexperience
{
    public int Id { get; set; }

    public int UserId { get; set; }

    [MaxLength(50)]
    public string Name { get; set; }
    
    public string Details { get; set; }

    public string Environment { get; set; }

    public DateTime? StartDate { get; set; }

    public DateTime? EndDate { get; set; }
}

public class User
{
    public int Id { get; set; }
    public string UserName { get; set; }
}

ublic class CursoEfContext : DbContext
{
    public virtual DbSet<User> Users { get; set; }

    public virtual DbSet<Wokringexperience> Wokringexperiences { get; set; }
    
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.
        => optionsBuilder.UseMySQL("server=127.0.0.1;port=4306;database=cursoEF;user=root;password=cursoEFpass");
}

Ahora lo que vamos a hacer es generar las migraciones, para ello tenemos dos opciones.

A -  Desde la línea de comandos, nos ubicamos en la carpeta que contiene el csproj del proyecto que contiene el DbContext y ejecutamos el siguiente  código:

dotnet ef migrations add MigracionInicial

 

B - en la consola de nuget (package manager console) ejecutamos el siguiente comando:

add-migration MigracionInicial

 

Ambas opciones nos van a dar el mismo resultado, el cual consiste en los siguientes 3 ficheros:

resultado migraciones

1 - El primero es el fichero principal de la migración y contiene las operaciones de Up y Down. y si lo abrimos, podemos ver cómo Up contiene toda la información de crear la base de datos mientras que Down contiene la información para destruir lo creado con Up.

public partial class MigracionInicial : Migration
{
    /// <inheritdoc />
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterDatabase()
            .Annotation("MySQL:Charset", "utf8mb4");

        migrationBuilder.CreateTable(
            name: "Users",
            columns: table => new
            {
                Id = table.Column<int>(type: "int", nullable: false)
                    .Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn),
                UserName = table.Column<string>(type: "longtext", nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Users", x => x.Id);
            })
            .Annotation("MySQL:Charset", "utf8mb4");

        migrationBuilder.CreateTable(
            name: "Wokringexperiences",
            columns: table => new
            {
                Id = table.Column<int>(type: "int", nullable: false)
                    .Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn),
                UserId = table.Column<int>(type: "int", nullable: false),
                Name = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: false),
                Details = table.Column<string>(type: "longtext", nullable: false),
                Environment = table.Column<string>(type: "longtext", nullable: false),
                StartDate = table.Column<DateTime>(type: "datetime(6)", nullable: true),
                EndDate = table.Column<DateTime>(type: "datetime(6)", nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Wokringexperiences", x => x.Id);
            })
            .Annotation("MySQL:Charset", "utf8mb4");
    }

    /// <inheritdoc />
    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropTable(
            name: "Users");

        migrationBuilder.DropTable(
            name: "Wokringexperiences");
    }
}

Esto se hace, principalmente, por si algo sale mal, para que podamos hacer un rollback de una forma sencilla.  

 

2 - El fichero designer contiene los metadatos utilizados por Entity Framework Core.

3 - El fichero Snapshot es una “imagen” del modelo actual, es el fichero que utiliza Entity Framework Core, para detectar qué ha cambiado desde la última migración. 

 

2.1 - Ejecutar migraciones en Entity Framework Core

Antes de continuar, asegúrate de que tienes tu base de datos corriendo y la conexión string es correcta, en mi caso estoy utilizando MySql.

 

Como mencioné en el post anterior, esta acción se solía hacer por línea de comandos, pero hoy en día se puede hacer en el código. La cual es asegurarse de que la base de datos se sincroniza con la migración que tienes en el código. 

 

En mi caso no tengo base de datos creada, por lo que la migración la creará, además de crear las tablas.

 

vamos al código y en nuestro startup.cs nos aseguramos de que el siguiente código esta presente para que la migración sea ejecutada

using (var scope = app.Services.CreateScope())
{
    CursoEfContext context = scope.ServiceProvider.GetRequiredService<CursoEfContext>();
    context.Database.Migrate();
}

Y ya está, simplemente ejecutamos el proyecto. 

resultado ejecutar migración

Esta acción nos ha creado ambas tablas y además una tabla adicional que contiene la información de las migraciones que han sido ejecutadas, para así saber en qué ‘versión’ de la migración está tu base de datos. 

 

 

3 - Actualizar una base de datos con migrations en Entity Framework Core

Migrations está dentro de code first, lo que quiere decir que si tenemos que actualizar la base de datos, lo haremos a través de las propias migraciones.

Para nuestro escenario, vamos a añadir un nuevo campo dentro de la tabla Users, en este caso el email. Lo primero que tenemos que hacer es ir a nuestra entidad y añadir dicha propiedad:

public class User
{
    public int Id { get; set; }
    public string UserName { get; set; }
    [MaxLength(50)]
    public string Email { get; set; }
}

 

Y ahora debemos crear una nueva migración, intenta siempre darle un nombre que tenga sentido, que eso siempre ayuda. 

dotnet ef migrations add AddEmailtoUser

Este comando nos va a crear el nuevo fichero de migración con su respectivo Up and Down.

public partial class AddEmailtoUser : Migration
{
    /// <inheritdoc />
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AddColumn<string>(
            name: "Email",
            table: "Users",
            type: "varchar(50)",
            maxLength: 50,
            nullable: false,
            defaultValue: "");
    }

    /// <inheritdoc />
    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropColumn(
            name: "Email",
            table: "Users");
    }
}

Así como la actualización automática del Snapshot.

 

Ahora, cuando ejecutemos el código, Entity Framework se encarga de actualizar todo lo que tenga que actualizar para que tu base de datos encaje con el modelo en tú código.

 

En este caso simplemente incluye la nueva columna y además incluye el nuevo registro en la tabla de migraciones. Este es el resultado después de ejecutar la aplicación:

update migrations result

Cómo vemos es lo esperado. 

 

4 - Revertir una migración en Entity Framework core

Qué sucece, si, durante la migración la hemos liado o la aplicación no esta bien testeada por lo que sea y hay que volver a la versión antigua, pero la base de datos esta a medias entre estar completo y la versión anterior? que nos toca deshacer la migración.

 

Nota: Para este escenario solo nos queda ejecutarla desde la línea de comandos o del package manager. Los comandos son los siguientes.

 

1 - Línea de comandos:

dotnet ef database update <NombreVersionAnteior>

2 - Package manager

Update-Database <NombreVersionAnteior>

 

Básicamente en NombreVersionAnteior debemos poner el nombre de la migración, en nuestro caso vamos a deshacer la última migración, para ello ejecutamos el comando 

dotnet ef database update MigracionInicial

y podemos ver cómo nos devuelve el aviso de que ha revertido la migración anterior

migracion revertida

Y en la base de datos por supuesto no queda rastro, por lo que podríamos volver tranquilamente a desplegar la versión anterior del código. 

  • NOTA: Si por algún motivo, quitas el código de la parte de Down en la migración, revertirla no causaría ningún efecto. 

 

4.1 - Eliminar una migración

En caso de que esa migración que has creado fuera errónea, no nos sirve con simplemente borrarla del código, ya que el fichero snapshot está modificado. 

Lo que tendríamos que hacer es eliminarla con el comando dotnet ef migrations remove, este comando elimina la última migración y pone el snapshot a como estaba anteriormente

 

 

conclusión.

En resumen, las migraciones son una herramienta muy útil para mantener tu base de datos sincronizada con el modelo de tu aplicación. 

Con Entity Framework Core, puedes generar migraciones de manera automática y aplicarlas fácilmente a la base de datos con code first.

 


Uso del bloqueador de anuncios adblock

Hola!

Primero de todo bienvenido a la web de NetMentor donde podrás aprender programación en C# y .NET desde un nivel de principiante hasta más avanzado.


Yo entiendo que utilices un bloqueador de anuncios como AdBlock, Ublock o el propio navegador Brave. Pero te tengo que pedir por favor que desactives el bloqueador para esta web.


Intento personalmente no poner mucha publicidad, la justa para pagar el servidor y por supuesto que no sea intrusiva; Si pese a ello piensas que es intrusiva siempre me puedes escribir por privado o por Twitter a @NetMentorTW.


Si ya lo has desactivado, por favor recarga la página.


Un saludo y muchas gracias por tu colaboración

© copyright 2024 NetMentor | Todos los derechos reservados | RSS Feed

Buy me a coffee Invitame a un café