Migraciones automáticas de Code First

Las Migraciones automáticas le permiten usar migraciones de Code First sin tener un archivo de código en el proyecto para cada cambio que realice. No todos los cambios se pueden aplicar automáticamente; por ejemplo, los cambios de nombre de columna requieren el uso de una migración basada en código.

Nota:

En este artículo se da por supuesto que sabe cómo usar Migraciones de Code First en escenarios básicos. Si no es así, debe leer Migraciones de Code First antes de continuar.

Recomendación para entornos de equipo

Puede intercalar migraciones automáticas y basadas en código, pero esto no se recomienda en escenarios de desarrollo en equipo. Si forma parte de un equipo de desarrolladores que usan el control de código fuente, debe usar migraciones puramente automáticas o migraciones puramente basadas en código. Dadas las limitaciones de las migraciones automáticas, se recomienda usar migraciones basadas en código en entornos de equipos.

Creación de un modelo inicial y una base de datos

Antes de empezar a usar Migraciones, se necesitan un proyecto y un modelo de Code First con los que trabajar. En este tutorial se va a usar el modelo canónico Blog y Post.

  • Creación de una nueva aplicación de consola MigrationsAutomaticDemo
  • Agregue la versión más reciente del paquete NuGet de EntityFramework al proyecto
    • Herramientas –> Administrador de paquetes de biblioteca–> Consola del Administrador de paquetes
    • Ejecute el comando Install-Package EntityFramework
  • Agregue un archivo Model.cs con el código que se muestra a continuación. Este código define una sola clase Blog que conforma el modelo de dominio y una clase BlogContext que es el contexto de EF Code First
    using System.Data.Entity;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Data.Entity.Infrastructure;

    namespace MigrationsAutomaticDemo
    {
        public class BlogContext : DbContext
        {
            public DbSet<Blog> Blogs { get; set; }
        }

        public class Blog
        {
            public int BlogId { get; set; }
            public string Name { get; set; }
        }
    }
  • Ahora que tenemos un modelo, es hora de usarlo para el acceso a los datos. Actualice el archivo Program.cs con el código que se muestra a continuación.
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace MigrationsAutomaticDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (var db = new BlogContext())
                {
                    db.Blogs.Add(new Blog { Name = "Another Blog " });
                    db.SaveChanges();

                    foreach (var blog in db.Blogs)
                    {
                        Console.WriteLine(blog.Name);
                    }
                }

                Console.WriteLine("Press any key to exit...");
                Console.ReadKey();
            }
        }
    }
  • Ejecute la aplicación y verá que se ha creado automáticamente una base de datos MigrationsAutomaticCodeDemo.BlogContext.

    Database LocalDB

Habilitación de migraciones

Es hora de realizar más cambios en el modelo.

  • Vamos a introducir una propiedad Url en la clase Blog.
    public string Url { get; set; }

Si volviera a ejecutar la aplicación, aparecería una excepción InvalidOperationException con el texto El modelo que respalda el contexto "BlogContext" ha cambiado desde que se creó la base de datos. Considere la posibilidad de usar Migraciones de Code First para actualizar la base de datos (http://go.microsoft.com/fwlink/?LinkId=238269).

Como sugiere la excepción, es hora de empezar a usar Migraciones de Code First. Dado que queremos usar migraciones automáticas, vamos a especificar el modificador –EnableAutomaticMigrations.

  • Ejecute el comando Enable-Migrations –EnableAutomaticMigrations en la consola del Administrador de paquetes. Este comando ha agregado una carpeta Migrations al proyecto. Esta nueva carpeta contiene un archivo:

  • La clase Configuration. Esta clase permite configurar el comportamiento de Migraciones en el contexto. En este tutorial se usa la configuración predeterminada. Puesto que hay un solo contexto de Code First en el proyecto, Enable-Migrations ha rellenado automáticamente el tipo de contexto al que se aplica esta configuración.

 

Su primera migración automática

Migraciones de Code First tiene dos comandos principales con los que se va a familiarizar.

  • Add-Migration aplica la técnica scaffolding a la siguiente migración en función de los cambios realizados en el modelo desde la creación de la última migración
  • Update-Database aplica las migraciones pendientes a la base de datos

Vamos a evitar el uso de Add-Migration (a menos que sea necesario) y centrarnos en permitir que las migraciones de Code First calculen y apliquen automáticamente los cambios. Vamos a usar Update-Database para obtener migraciones de Code First para insertar los cambios en nuestro modelo (la nueva propiedad Blog.Url) en la base de datos.

  • Ejecute el comando Update-Database en la consola del administrador de paquetes.

La base de datos MigrationsAutomaticDemo.BlogContext se ha actualizado para incluir la columna Url en la tabla Blogs.

 

Su segunda migración automática

Vamos a realizar otro cambio y dejar que las Migraciones de Code First inserten automáticamente los cambios en la base de datos.

  • También vamos a agregar una nueva clase Post
    public class Post
    {
        public int PostId { get; set; }
        [MaxLength(200)]
        public string Title { get; set; }
        public string Content { get; set; }

        public int BlogId { get; set; }
        public Blog Blog { get; set; }
    }
  • Además agregaremos una colección Posts a la clase Blog para formar el otro extremo de la relación entre Blog y Post
    public virtual List<Post> Posts { get; set; }

Ahora use Update-Database para actualizar la base de datos. Esta vez vamos a especificar la marca -Verbose para que pueda ver el SQL que ejecuta Migraciones de Code First.

  • Ejecute el comando Update-Database –Verbose en la consola del Administrador de paquetes.

Adición de una migración basada en código

Ahora echemos un vistazo a algo para lo que podríamos querer usar una migración basada en código.

  • Vamos a agregar una propiedad Clasificación a la clase Blog
    public int Rating { get; set; }

Podríamos ejecutar Update-Database para insertar estos cambios en la base de datos. Sin embargo, vamos a agregar una columna Blogs.Rating que no acepta valores nulos. Si hay datos existentes en la tabla, se le asignará el valor predeterminado CLR del tipo de datos para la nueva columna (Clasificación es un valor entero, por lo que sería 0). Pero queremos especificar un valor predeterminado de 3, para que las filas existentes en la tabla Blogs comiencen con una clasificación decente. Vamos a usar el comando Add-Migration para escribir este cambio en una migración basada en código para poder editarlo. El comando Add-Migration permite poner un nombre a estas migraciones; a la nuestra la llamaremos AddBlogRating.

  • Ejecute el comando Add-Migration AddBlogRating en la consola del Administrador de paquetes.
  • En la carpeta Migraciones ahora tenemos una nueva migración AddBlogRating. El nombre de archivo de la migración lleva una marca de tiempo para ayudar con el orden. Vamos a editar el código generado para especificar un valor predeterminado de 3 para Blog.Rating (línea 10 en el código siguiente)

La migración también tiene un archivo de código subyacente que captura algunos metadatos. Estos metadatos permitirán que las migraciones de Code First repliquen las migraciones automáticas que hemos realizado antes de esta migración basada en código. Esto es importante si otro desarrollador quiere ejecutar nuestras migraciones o cuando es el momento de implementar nuestra aplicación.

    namespace MigrationsAutomaticDemo.Migrations
    {
        using System;
        using System.Data.Entity.Migrations;

        public partial class AddBlogRating : DbMigration
        {
            public override void Up()
            {
                AddColumn("Blogs", "Rating", c => c.Int(nullable: false, defaultValue: 3));
            }

            public override void Down()
            {
                DropColumn("Blogs", "Rating");
            }
        }
    }

La migración editada tiene buen aspecto, así que vamos a usar Update-Database para actualizar la base de datos.

  • Ejecute el comando Update-Database en la consola del administrador de paquetes.

Volver a Migraciones automáticas

Ahora ya podemos volver a las migraciones automáticas para nuestros cambios más sencillos. Las Migraciones de Code First se encargarán de realizar las migraciones automáticas y basadas en código en el orden correcto en función de los metadatos que almacena en el archivo de código subyacente para cada migración basada en código.

  • Agreguemos una propiedad Post.Abstract al modelo
    public string Abstract { get; set; }

Ahora podemos usar Update-Database para obtener migraciones de Code First para insertar este cambio en la base de datos mediante una migración automática.

  • Ejecute el comando Update-Database en la consola del administrador de paquetes.

Resumen

En este tutorial, ha visto cómo usar migraciones automáticas para insertar cambios de modelo en la base de datos. También ha visto cómo aplicar andamiaje y ejecutar migraciones basadas en código entre migraciones automáticas cuando necesita más control.