Traducción: Primeros pasos con Entity Framework 6 de MVC5 (5) - Código de primera migración e implementación de Entity Framework en el programa MVC

Code First Migration and Deployment of Entity Framework en el programa MVC

Esta es una traducción del tutorial oficial de Microsoft Comenzando con Entity Framework 6 Code First usando la serie MVC 5, que es el quinto artículo: Code First Migration and Deployment of Entity Framework en MVC Program

: :Codifique primero las migraciones y la implementación con Entity Framework en una aplicación ASP.NET MVC


Hasta ahora, la aplicación ya puede ejecutarse normalmente en su máquina local. Pero si desea publicarlo en Internet para que lo utilicen más personas, debe implementar el programa en el servidor WEB. En este tutorial implementará la aplicación Contoso University en la nube del sitio web de Windows Azure.

Este tutorial contiene los siguientes capítulos:

  • Habilite la migración de Code First. La función de migración le permite realizar cambios en el modelo de datos e implementar sus cambios en el entorno de producción sin eliminar y volver a crear la estructura de datos de la base de datos.
  • Implemente la aplicación en Windows Azure. Este paso es opcional, puede omitir este paso para continuar con los tutoriales restantes.

Recomendamos implementar utilizando un proceso de integración continua controlado por código fuente, pero este tutorial no cubre esos temas. Para obtener más información, consulte control de origen y Creación de aplicaciones en la nube del mundo real con Windows Azure .

Habilitar la migración de Code First

Cuando desarrolla nuevas aplicaciones, su modelo de datos cambia con frecuencia. Y con cada cambio, el modelo de datos se desconecta de la base de datos. Ha configurado correctamente Entity Framework para eliminar y volver a crear automáticamente la base de datos cada vez que cambie el modelo de datos. Cuando agrega, elimina o cambia una clase de entidad o cambia su clase de DbContext, volver a ejecutar la aplicación hará que elimine automáticamente la base de datos existente y cree una base de datos que coincida con el modelo de datos actual. Y complete los datos de prueba.

Este enfoque hace un muy buen trabajo al mantener sincronizados el modelo de datos y el esquema de la base de datos hasta que esté listo para implementar la aplicación en un entorno de producción. Cuando la aplicación inicia la producción y almacena datos de producción, ciertamente no desea perder los datos de producción debido a cambios en el modelo de datos (como agregar una nueva columna). La función Code First Migrations resuelve este problema. Actualice el esquema de la base de datos habilitando la migración de Code First en lugar de eliminar y reconstruir la base de datos. En este tutorial, implementará la aplicación y se preparará para habilitar la migración.

Deshabilite la configuración inicial que estableció en Web.Config en el tutorial anterior.

<entityFramework>
  <!--<contexts>
    <context type="ContosoUniversity.DAL.SchoolContext, ContosoUniversity">
      <databaseInitializer type="ContosoUniversity.DAL.SchoolInitializer, ContosoUniversity" />
    </context>
  </contexts>-->
  <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
    <parameters>
      <parameter value="v11.0" />
    </parameters>
  </defaultConnectionFactory>
  <providers>
    <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
  </providers>
</entityFramework>

También en Web.config, cambie el nombre de la cadena de conexión de la base de datos a ContosoUniversity2.

<connectionStrings>
  <add name="SchoolContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=ContosoUniversity2;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
</connectionStrings>

Este cambio establece la primera migración del proyecto para crear una nueva base de datos, lo cual no es necesario, pero verá más adelante que es una buena idea hacerlo.

En el menú Herramientas, haga clic en NuGet Package Manager y haga clic en Package Manager Console.

1 p.m.

Ingrese el siguiente comando en la consola:

enable-migrations
add-migration InitialCreate

pmcenablemigrations

El comando enable-migrations creará una carpeta de migración en el proyecto. Al mismo tiempo, la carpeta contiene un archivo Configuration.cs, que puede editar para configurar la migración. Si no cambió el nombre de la base de datos en el paso anterior, la migración encontrará la base de datos existente y ejecutará automáticamente el comando agregar-migración, no importa. Simplemente significa que no ejecutará una prueba del código de migración antes de implementar la base de datos. Después de eso, cuando ejecuta update-database, no se realizarán cambios porque la base de datos ya existe.

archivo de migraciones

Como en el tutorial anterior, el método Seed también se incluye en la clase Configuration.

internal sealed class Configuration : DbMigrationsConfiguration<ContosoUniversity.DAL.SchoolContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(ContosoUniversity.DAL.SchoolContext context)
    {
        //  This method will be called after migrating to the latest version.

        //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
        //  to avoid creating duplicate seed data. E.g.
        //
        //    context.People.AddOrUpdate(
        //      p => p.FullName,
        //      new Person { FullName = "Andrew Peters" },
        //      new Person { FullName = "Brice Lambson" },
        //      new Person { FullName = "Rowan Miller" }
        //    );
        //
    }
}

El propósito del método Seed es permitirle insertar o actualizar datos de prueba después de que Code First cree o actualice la base de datos. Se llamará a este método cada vez que la base de datos cree y actualice el esquema de la base de datos.

Establecer método de semilla

Cada vez que cambie el modelo de datos, puede usar el método Seed de la clase inicial para insertar datos de prueba cuando elimine y vuelva a crear la base de datos. Debido a que cada vez que el modelo cambia la base de datos, la base de datos se eliminará y se perderán todos los datos de prueba. En el primero de Code First, los datos de prueba se retienen después de cambiar la base de datos. Por lo tanto, generalmente no es necesario incluir datos de prueba en el método Seed. De hecho, no desea que el método Seed inserte datos de prueba al usar la migración para implementar la base de datos en el entorno de producción, porque el método Seed se llamará en el entorno de producción. En este caso, el método Seed se usa para insertar datos en el entorno de producción solo cuando realmente se necesita. Por ejemplo, es posible que desee incluir el nombre real del departamento en la tabla Departamento cuando realice la implementación en un entorno de producción.

Para este tutorial, utilizará la migración para implementar. Pero para permitirle ver fácilmente cómo la función del programa inserta datos sin operación manual, utilizaremos el método Seed para insertar datos de prueba.

Use el siguiente código para reemplazar el contenido del archivo Configuration.cs:

namespace ContosoUniversity.Migrations
{
    using ContosoUniversity.Models;
    using System;
    using System.Collections.Generic;
    using System.Data.Entity;
    using System.Data.Entity.Migrations;
    using System.Linq;

    internal sealed class Configuration : DbMigrationsConfiguration<ContosoUniversity.DAL.SchoolContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
        }

        protected override void Seed(ContosoUniversity.DAL.SchoolContext context)
        {
            var students = new List<Student>
            {
                new Student { FirstMidName = "Carson",   LastName = "Alexander", 
                    EnrollmentDate = DateTime.Parse("2010-09-01") },
                new Student { FirstMidName = "Meredith", LastName = "Alonso",    
                    EnrollmentDate = DateTime.Parse("2012-09-01") },
                new Student { FirstMidName = "Arturo",   LastName = "Anand",     
                    EnrollmentDate = DateTime.Parse("2013-09-01") },
                new Student { FirstMidName = "Gytis",    LastName = "Barzdukas", 
                    EnrollmentDate = DateTime.Parse("2012-09-01") },
                new Student { FirstMidName = "Yan",      LastName = "Li",        
                    EnrollmentDate = DateTime.Parse("2012-09-01") },
                new Student { FirstMidName = "Peggy",    LastName = "Justice",   
                    EnrollmentDate = DateTime.Parse("2011-09-01") },
                new Student { FirstMidName = "Laura",    LastName = "Norman",    
                    EnrollmentDate = DateTime.Parse("2013-09-01") },
                new Student { FirstMidName = "Nino",     LastName = "Olivetto",  
                    EnrollmentDate = DateTime.Parse("2005-08-11") }
            };
            students.ForEach(s => context.Students.AddOrUpdate(p => p.LastName, s));
            context.SaveChanges();

            var courses = new List<Course>
            {
                new Course {CourseID = 1050, Title = "Chemistry",      Credits = 3, },
                new Course {CourseID = 4022, Title = "Microeconomics", Credits = 3, },
                new Course {CourseID = 4041, Title = "Macroeconomics", Credits = 3, },
                new Course {CourseID = 1045, Title = "Calculus",       Credits = 4, },
                new Course {CourseID = 3141, Title = "Trigonometry",   Credits = 4, },
                new Course {CourseID = 2021, Title = "Composition",    Credits = 3, },
                new Course {CourseID = 2042, Title = "Literature",     Credits = 4, }
            };
            courses.ForEach(s => context.Courses.AddOrUpdate(p => p.Title, s));
            context.SaveChanges();

            var enrollments = new List<Enrollment>
            {
                new Enrollment { 
                    StudentID = students.Single(s => s.LastName == "Alexander").ID, 
                    CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID, 
                    Grade = Grade.A 
                },
                 new Enrollment { 
                    StudentID = students.Single(s => s.LastName == "Alexander").ID,
                    CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID, 
                    Grade = Grade.C 
                 },                            
                 new Enrollment { 
                    StudentID = students.Single(s => s.LastName == "Alexander").ID,
                    CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID, 
                    Grade = Grade.B
                 },
                 new Enrollment { 
                     StudentID = students.Single(s => s.LastName == "Alonso").ID,
                    CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID, 
                    Grade = Grade.B 
                 },
                 new Enrollment { 
                     StudentID = students.Single(s => s.LastName == "Alonso").ID,
                    CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID, 
                    Grade = Grade.B 
                 },
                 new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Alonso").ID,
                    CourseID = courses.Single(c => c.Title == "Composition" ).CourseID, 
                    Grade = Grade.B 
                 },
                 new Enrollment { 
                    StudentID = students.Single(s => s.LastName == "Anand").ID,
                    CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID
                 },
                 new Enrollment { 
                    StudentID = students.Single(s => s.LastName == "Anand").ID,
                    CourseID = courses.Single(c => c.Title == "Microeconomics").CourseID,
                    Grade = Grade.B         
                 },
                new Enrollment { 
                    StudentID = students.Single(s => s.LastName == "Barzdukas").ID,
                    CourseID = courses.Single(c => c.Title == "Chemistry").CourseID,
                    Grade = Grade.B         
                 },
                 new Enrollment { 
                    StudentID = students.Single(s => s.LastName == "Li").ID,
                    CourseID = courses.Single(c => c.Title == "Composition").CourseID,
                    Grade = Grade.B         
                 },
                 new Enrollment { 
                    StudentID = students.Single(s => s.LastName == "Justice").ID,
                    CourseID = courses.Single(c => c.Title == "Literature").CourseID,
                    Grade = Grade.B         
                 }
            };

            foreach (Enrollment e in enrollments)
            {
                var enrollmentInDataBase = context.Enrollments.Where(
                    s =>
                         s.Student.ID == e.StudentID &&
                         s.Course.CourseID == e.CourseID).SingleOrDefault();
                if (enrollmentInDataBase == null)
                {
                    context.Enrollments.Add(e);
                }
            }
            context.SaveChanges();
        }
    }
}

El método Seed usa el objeto de contexto de la base de datos como parámetro de entrada y usa este objeto en el código para agregar nuevas entidades a la base de datos. Para cada tipo de entidad, el código crea una nueva colección de entidades y las agrega a las propiedades apropiadas de DbSet, luego guarda los cambios en la base de datos. No es necesario llamar al método SaveChanges inmediatamente después de cada grupo de entidades, pero hacerlo le permite localizar más fácilmente el origen del problema cuando se produce un problema.

La mayoría de las declaraciones que insertan objetos utilizan el método AddOrUpdate para realizar operaciones "upsert". Debido a que el método Seed se ejecuta cada vez que ejecuta el comando de actualización de la base de datos, generalmente no puede simplemente insertar datos después de cada migración. Debido a que la fila que está intentando agregar ya puede existir en la primera migración después de crear la base de datos. La operación "upsert" le impide intentar agregar una fila existente, pero reescribirá los cambios que realizó en los datos durante la fase de prueba. Es posible que no desee que esto suceda en algunas tablas de datos: en algunos casos, es posible que desee conservar los cambios que realizó en los datos de prueba durante la fase de prueba. En este caso, debe realizar una operación de inserción condicional: inserte filas solo si no existe. El método Seed utiliza los dos métodos anteriores.

El primer parámetro pasado al método AddOrUpdate, un atributo especificado se utiliza para verificar si la fila ya existe. Para los datos del alumno de prueba que proporcione, el atributo Apellido puede usarse para verificar si la entidad es única en cada lista.

context.Students.AddOrUpdate(p => p.LastName, s)

Este código supone que LastName es único. Si agrega manualmente estudiantes con apellido duplicado, obtendrá una excepción de "secuencia contiene varios elementos". Para obtener información sobre cómo manejar datos sencillos, consulte Sembrar y depurar bases de datos del Marco de entidad (EF). Para obtener más información sobre el método AddOrUpdate, consulte Cuidado con el método EF 4.3 AddOrUpdate. El código para crear la entidad de inscripción supone que la entidad en la colección de estudiantes ya tiene un valor de ID, aunque no estableció este valor en el código para crear la colección.

new Enrollment { 
    StudentID = students.Single(s => s.LastName == "Alexander").ID, 
    CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID, 
    Grade = Grade.A 
},

Puede usar el valor de ID aquí porque el valor de ID se establece cuando llama al método SaveChanges para la colección de estudiantes. Cuando se inserta una entidad en la base de datos, el marco de la entidad obtendrá automáticamente el valor de la clave primaria de la entidad y actualizará el atributo ID en la memoria de la entidad. El código que agrega cada entidad de inscripción a la colección de entidades de inscripciones no utiliza el método AddOrUpdate, verifica si cada entidad existe y, si no, inserta la entidad. Este método retendrá los cambios realizados en la calificación mediante el uso de la interfaz de usuario de la aplicación. El código atraviesa a cada miembro de la lista de inscripción. Si el miembro no existe en la base de datos, agréguelo a la base de datos. Cuando actualiza la base de datos por primera vez, la base de datos está vacía, por lo que se agregarán todas las entidades de inscripción en la colección.

foreach (Enrollment e in enrollments)
{
    var enrollmentInDataBase = context.Enrollments.Where(
        s => s.Student.ID == e.Student.ID &&
             s.Course.CourseID == e.Course.CourseID).SingleOrDefault();
    if (enrollmentInDataBase == null)
    {
        context.Enrollments.Add(e);
    }
}

Construye el proyecto.

Realizar la primera migración

Cuando ejecute el comando add-migración, la migración generará código para crear la base de datos. El código también está en la carpeta Migraciones, en el archivo llamado <Timestamp> _InitalCreate.cs. El método Up en esta clase creará tablas de base de datos de acuerdo con el conjunto de entidades del modelo de datos, y el método Down se usa para eliminarlas.

public partial class InitialCreate : DbMigration
{
    public override void Up()
    {
        CreateTable(
            "dbo.Course",
            c => new
                {
                    CourseID = c.Int(nullable: false),
                    Title = c.String(),
                    Credits = c.Int(nullable: false),
                })
            .PrimaryKey(t => t.CourseID);

        CreateTable(
            "dbo.Enrollment",
            c => new
                {
                    EnrollmentID = c.Int(nullable: false, identity: true),
                    CourseID = c.Int(nullable: false),
                    StudentID = c.Int(nullable: false),
                    Grade = c.Int(),
                })
            .PrimaryKey(t => t.EnrollmentID)
            .ForeignKey("dbo.Course", t => t.CourseID, cascadeDelete: true)
            .ForeignKey("dbo.Student", t => t.StudentID, cascadeDelete: true)
            .Index(t => t.CourseID)
            .Index(t => t.StudentID);

        CreateTable(
            "dbo.Student",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    LastName = c.String(),
                    FirstMidName = c.String(),
                    EnrollmentDate = c.DateTime(nullable: false),
                })
            .PrimaryKey(t => t.ID);

    }

    public override void Down()
    {
        DropForeignKey("dbo.Enrollment", "StudentID", "dbo.Student");
        DropForeignKey("dbo.Enrollment", "CourseID", "dbo.Course");
        DropIndex("dbo.Enrollment", new[] { "StudentID" });
        DropIndex("dbo.Enrollment", new[] { "CourseID" });
        DropTable("dbo.Student");
        DropTable("dbo.Enrollment");
        DropTable("dbo.Course");
    }
}

La migración llama al método Up para implementar los cambios realizados por el modelo de datos. Cuando ingresa un comando para revertir la actualización, la migración llamará al método Down.

Esta es la migración inicial creada cuando ingresa el comando add-migración InitialCreate. El parámetro (InitialCreate en este ejemplo) se usa para el nombre del archivo, pero también puede ser cualquier otro nombre que desee. Por lo general, elegirá una palabra o frase para resumir los cambios realizados durante la migración. Por ejemplo, puede nombrar la migración a "AddDeparmentTable".

Si crea una migración donde la base de datos ya existe, el código de creación de la base de datos generado no se ejecutará. Porque la base de datos ya coincide con el modelo de datos. Cuando la aplicación se implementa en otro entorno donde la base de datos no se ha creado, el código se ejecutará para crear la base de datos. Por lo tanto, es mejor hacer una prueba por adelantado. Es por eso que cambió el nombre de la base de datos en la cadena de conexión antes, para que la migración pueda crear una nueva base de datos desde cero.

En la consola del administrador de paquetes, ingrese el siguiente comando:

update-database

actualizar base de datos

El comando update-database ejecuta el método Up para crear la base de datos y luego ejecuta el método Seed para llenar la base de datos. El mismo proceso ocurrirá cuando el programa se implemente en el entorno de producción, como verá en la siguiente sección. Use el administrador de administración de activos del servidor para verificar la base de datos y verificar que los datos y los programas que contiene estén funcionando como antes.

Implementar en Windows Azure

Debido a que no tenemos una cuenta de prueba para Windows Azure, esta parte de la traducción se omite ... No afecta el aprendizaje de todos modos.

Resumen

En esta sección viste cómo migrar usando Code First. En la siguiente sección comenzarás a abordar temas avanzados y ampliar el modelo de datos.

Información del autor

tom-dykstra Tom Dykstra -Tom Dykstra es un programador senior y escritor en el equipo de Microsoft Web Platform and Tools.

Publicó 40 artículos originales · 25 alabanzas · 100,000+ vistas

Supongo que te gusta

Origin blog.csdn.net/yym373872996/article/details/52965750
Recomendado
Clasificación