Skip to content

Instantly share code, notes, and snippets.

@cgalvist
Created June 28, 2023 15:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cgalvist/6060250f214393eca3274c1f2b6c1108 to your computer and use it in GitHub Desktop.
Save cgalvist/6060250f214393eca3274c1f2b6c1108 to your computer and use it in GitHub Desktop.
Demostración EF Migrations

Introducción a Entity Framework Migrations

Tutorial

Original tomado de EF Core and SQLite: getting started on macOS and VS Code

Proyecto base con SQLite

Creación del proyecto

# Crear una carpeta para el proyecto
mkdir ef-migrations-demo && cd ef-migrations-demo
mkdir src && cd src
# Crear proyecto de consola con .net
dotnet new console
# Restaurar paquetes de NuGet
dotnet restore
# Agregar dependencia de SQLite
dotnet add package Microsoft.EntityFrameworkCore.Sqlite

Adición de clases

VideoGame.cs

using System.ComponentModel.DataAnnotations;

namespace src {
    public class VideoGame {

        [Key]
        public int Id { get; set; }

        public string Title { get; set; }

        public string Platform { get; set; }
    }
}

VideoGamesDbContext.cs

using Microsoft.EntityFrameworkCore;

namespace src
{
    public class VideoGamesDbContext : DbContext
    {
        public DbSet<VideoGame> VideoGames {get; set;}

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
            optionsBuilder.UseSqlite("Filename=./video_games.db");
        }
    }
}

Edición de clases

using System;
using System.Linq;

namespace src
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine ("Hello World EF Core!");

            using (var context = new VideoGamesDbContext()) {

                // Clear the database
                context.Database.EnsureDeleted();
                // Create the database if it does not exist
                context.Database.EnsureCreated ();

                // Add some video games. 
                // Note that the Id field is autoincremented by default
                context.VideoGames.Add (new VideoGame {
                    Title = "Super Mario Bros 3",
                    Platform = "SNES"
                });
                context.VideoGames.Add (new VideoGame {
                    Title = "Megaman ZX",
                    Platform = "NDS"
                });

                // Commit changes by calling save changes
                context.SaveChanges ();

                // Fetch all video games
                Console.WriteLine ("Current database content");
                foreach (var videoGame in context.VideoGames.ToList ())
                    PrintVideoGameData(videoGame);

                // Fetch all SNES games
                var snesGames = context.VideoGames.Where(v => v.Platform == "SNES");

                Console.WriteLine ("SNES Games");
                foreach (var videoGame in snesGames)
                    PrintVideoGameData(videoGame);

                // Delete SNES games
                Console.WriteLine ("Deleting SNES Games");
                context.VideoGames.RemoveRange (snesGames);

                context.SaveChanges ();
                Console.WriteLine ("Current database content");

                foreach (var videoGame in context.VideoGames)
                    PrintVideoGameData(videoGame);
            }
        }

        static void PrintVideoGameData(VideoGame videoGame)
        {
            Console.WriteLine ($"{videoGame.Title} - {videoGame.Platform}");
        }
    }
}

Compilar y ejecutar

dotnet build
dotnet run

Al ejecutar el programa, deberá mostrar los siguientes datos:

Hello World EF Core!
Current database content
Super Mario Bros 3 - SNES
Megaman ZX - NDS
SNES Games
Super Mario Bros 3 - SNES
Deleting SNES Games
Current database content
Megaman ZX - NDS

Puede verificar la base de datos utilizando el programa DB Browser y abriendo el archivo video_games.db ubicado en la carpeta src/

Migraciones con EF Core

# Instalar dependencias de EF Core
dotnet add package Microsoft.EntityFrameworkCore.Tools
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.Tools.DotNet
# Instalar herramientas de EF Core de manera global
dotnet tool install --global dotnet-ef
# Parche para que las herramientas funcionen en Linux
export PATH="$PATH:$HOME/.dotnet/tools/"

Crear migración inicial

Crearemos la migración inicial con la siguiente orden:

dotnet ef migrations add InitialMigration

Al terminar nos generará 3 clases en la carpeta Migrations. Estos 3 archivos en este caso nos permitirán crear una base de datos y una tabla con el modelo previamente hecho en el programa.

En estos momentos podremos hacer algunas cosas, como por ejemplo:

# Actualizar la base de datos
dotnet ef database update
# Crear script SQL
dotnet ef migrations script 0 InitialMigration -o ./script.sql
# Eliminar la última migración
dotnet ef migrations remove

Crear migración con modificaciones

En la clase VideoGame.cs agregaremos el atributo ReleaseYear para indicar el año de lanzamiento:

// Añadir esto a la clase VideoGame.cs
public int ReleaseYear { get; set; }

Luego creamos una nueva migración:

dotnet ef migrations add VideoGameAddReleaseYear

Con esta migración podremos hacer las mismas acciones que en la migración anterior:

# Actualizar la base de datos
dotnet ef database update
# Crear script SQL
dotnet ef migrations script InitialMigration VideoGameAddReleaseYear -o ./script.sql

Como demostración, eliminaremos la base de datos video_games.db y modificaremos los registros de la clase Program.cs agregando el año de lanzamiento de los videojuegos:

context.VideoGames.Add (new VideoGame {
    Title = "Super Mario Bros 3",
    Platform = "SNES",
    ReleaseYear = 1988
});
context.VideoGames.Add (new VideoGame {
    Title = "Megaman ZX",
    Platform = "NDS",
    ReleaseYear = 2006
});

Y cambiamos el resultado de la función PrintVideoGameData por la siguiente:

Console.WriteLine ($"{videoGame.Title} - {videoGame.Platform} - {videoGame.ReleaseYear}");

Comentaremos la línea en donde se elimina la base de datos al iniciar el programa:

//context.Database.EnsureDeleted();

Luego de estos cambios, ejecutamos las siguientes órdenes:

# Crear la base de datos inicial
dotnet ef database update InitialMigration
# Ejecutar el programa
dotnet run

Al ejecutar el programa se presentará una excepción, ya que estará intentando ingresar datos en la columna ReleaseYear, la cual no existe en la migración InitialMigration.

Para actualizar la estructura de la base de datos ejecutamos lo siguiente:

# Actualizar la base de datos
dotnet ef database update VideoGameAddReleaseYear
# Ejecutar el programa
dotnet run

Luego de esta ejecución, no se encontrará ningún problema y deberá imprimir la información de los videojuegos con su respectivo año de lanzamiento.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment