Traducción: Introducción a Entity Framework 6 de MVC5 (11) - Implementación de herencia para aplicaciones ASP.NET MVC

Implementar herencia para aplicaciones ASP.NET MVC

Esta es una traducción del tutorial oficial de Microsoft Comenzando con Entity Framework 6 Code Primero usando la serie MVC 5, aquí está el undécimo artículo: Implementando herencia para aplicaciones ASP.NET MVC

: :Implementación de herencia con Entity Framework 6 en una aplicación ASP.NET MVC 5


En el tutorial anterior, aprendió a manejar excepciones concurrentes. En este tutorial, presentaremos cómo implementar la herencia.

En la programación orientada a objetos, puede usar la herencia para reutilizar el código. En este tutorial, cambiará las clases de Instructor y Estudiante para que se deriven de la clase base Persona que contiene el atributo de nombre. No necesita cambiar ninguna página WEB, pero sus cambios se reflejarán automáticamente en la base de datos.

Opciones de mapeo heredadas a la base de datos

Las clases de Instructor y Estudiante en el modelo de datos tienen varias propiedades idénticas:

modelos

Suponga que desea eliminar el código redundante compartiendo los atributos de las entidades del profesor y del alumno, o desea escribir un servicio que no le importa si el nombre proviene del alumno o del profesor para formatear el nombre correctamente. Puede crear una clase base Persona que contenga estos atributos compartidos, y luego hacer que las clases de las entidades docentes y estudiantiles hereden de la clase base, como se muestra en la siguiente figura:

modelos

En la base de datos, esta estructura de herencia tiene varias manifestaciones. Puede crear una tabla de datos de persona, una sola tabla que contenga información del profesor y del alumno y del alumno, algunas columnas solo pueden aplicarse a los profesores (fecha de empleo), algunas solo se aplican a los alumnos (fecha de registro) y algunas ambas (Apellido, nombre). Por lo general, tendrá una columna de identificación para indicar el tipo representado por cada fila, por ejemplo, la columna de identificación puede usar "Instructor" para indicar un maestro y "Estudiante" para indicar un estudiante.

mesa

El modo de generar una estructura de herencia de entidad a partir de una única tabla de base de datos se denomina modo de herencia de tabla por capa.

La alternativa es utilizar una base de datos que se parezca más a una estructura de herencia. Por ejemplo, solo puede incluir atributos comunes a estudiantes y profesores en la tabla Persona y colocar atributos únicos en tablas separadas.

mesas

Hacer que cada clase de entidad establezca un modo de tabla de base de datos se convierte en una herencia de tabla para cada tipo.

Pero otra opción es asignar todos los tipos no abstractos a una sola tabla. Todas las categorías de atributos, incluidas las heredadas, se asignarán a columnas en la tabla correspondiente. Este patrón se llama herencia de una tabla por clase concreta. Si implementa la herencia de tablas de las clases específicas de las clases Persona, Estudiante e Instructor, las tablas de datos de Estudiante e Instructor serán las mismas que ha visto antes.

Una tabla por clase concreta y una tabla por capa en Entity Framework generalmente proporcionarán un mejor rendimiento que una tabla por tipo, porque una tabla por tipo puede generar consultas de unión complejas.

Este tutorial demostrará cómo implementar una herencia de tabla por capa. Una tabla por capa es el modo de herencia predeterminado de Entity Framework. Todo lo que tiene que hacer es crear una clase de Persona, modificar las clases de Instructor y Estudiante derivadas de Persona, agregar la nueva clase a DbContext y crear la migración.

Crear clase de persona

En la carpeta Modelos, use el siguiente código para crear la clase Persona:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
    public abstract class Person
    {
        public int ID { get; set; }

        [Required]
        [StringLength(50)]
        [Display(Name = "Last Name")]
        public string LastName { get; set; }
        [Required]
        [StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")]
        [Column("FirstName")]
        [Display(Name = "First Name")]
        public string FirstMidName { get; set; }

        [Display(Name = "Full Name")]
        public string FullName
        {
            get
            {
                return LastName + ", " + FirstMidName;
            }
        }
    }
}

Hacer que las clases de Alumno e Instructor hereden de Persona

En la clase Instructor, modifique la clase derivada de Persona y elimine el campo de nombre, como en el siguiente código:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
    public class Instructor : Person
    {
        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        [Display(Name = "Hire Date")]
        public DateTime HireDate { get; set; }

        public virtual ICollection<Course> Courses { get; set; }
        public virtual OfficeAssignment OfficeAssignment { get; set; }
    }
}

Modifique también la clase de estudiante:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
    public class Student : Person
    {
        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        [Display(Name = "Enrollment Date")]
        public DateTime EnrollmentDate { get; set; }

        public virtual ICollection<Enrollment> Enrollments { get; set; }
    }
}

Agregar tipo de entidad Persona al modelo

Agregue una propiedad de entidad Person DbSet a SchoolContext.cs:

public DbSet<Person> People { get; set; }

Es implementar todas las modificaciones necesarias para implementar la herencia en Entity Framework. Más adelante verá que después de actualizar la base de datos, habrá una nueva tabla de datos de Persona.

Crear y actualizar un archivo de migración

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

Add-Migration Inheritance

Después de ejecutar el comando update-database, el comando fallará. Debido a que Entity Framework no sabe cómo migrar nuestros datos existentes, el mensaje de error es similar al siguiente:

No se pudo colocar el objeto 'dbo.Instructor' porque se hace referencia a él mediante una restricción FOREIGN KEY.

Abra el archivo Migrations \ <Timestamp> -Inheritance.cs y reemplace el método Up con el siguiente código:

public override void Up()
{
    // Drop foreign keys and indexes that point to tables we're going to drop.
    DropForeignKey("dbo.Enrollment", "StudentID", "dbo.Student");
    DropIndex("dbo.Enrollment", new[] { "StudentID" });

    RenameTable(name: "dbo.Instructor", newName: "Person");
    AddColumn("dbo.Person", "EnrollmentDate", c => c.DateTime());
    AddColumn("dbo.Person", "Discriminator", c => c.String(nullable: false, maxLength: 128, defaultValue: "Instructor"));
    AlterColumn("dbo.Person", "HireDate", c => c.DateTime());
    AddColumn("dbo.Person", "OldId", c => c.Int(nullable: true));

    // Copy existing Student data into new Person table.
    Sql("INSERT INTO dbo.Person (LastName, FirstName, HireDate, EnrollmentDate, Discriminator, OldId) SELECT LastName, FirstName, null AS HireDate, EnrollmentDate, 'Student' AS Discriminator, ID AS OldId FROM dbo.Student");

    // Fix up existing relationships to match new PK's.
    Sql("UPDATE dbo.Enrollment SET StudentId = (SELECT ID FROM dbo.Person WHERE OldId = Enrollment.StudentId AND Discriminator = 'Student')");

    // Remove temporary key
    DropColumn("dbo.Person", "OldId");

    DropTable("dbo.Student");

    // Re-create foreign keys and indexes pointing to new table.
    AddForeignKey("dbo.Enrollment", "StudentID", "dbo.Person", "ID", cascadeDelete: true);
    CreateIndex("dbo.Enrollment", "StudentID");
}

Este código realiza las siguientes tareas de actualización de la base de datos:

  • Se eliminaron las restricciones e índices de clave externa que apuntan a la tabla de datos del alumno

  • Se cambió el nombre de la tabla de Instructor a la tabla de Persona y se modificó:

    • Se agregó una fecha de inscripción vacía para estudiantes
    • Se agregó una columna de identificación para indicar si la fila es un estudiante o un maestro
    • Ponga la fecha de empleo en blanco, porque el viaje del estudiante no tendrá una fecha de empleo
    • Agregue un campo temporal para actualizar la clave externa para el alumno. Cuando copie a los alumnos de nuevo a la tabla Persona, tendrán un nuevo valor de clave principal.
  • Copie los datos de la tabla del alumno a la tabla Persona, lo que hace que el alumno tenga un nuevo valor de clave primaria

  • Se corrigieron valores de clave externa que apuntaban a estudiantes

  • Recrea restricciones e índices de clave externa, ahora apuntan a la tabla Persona

(Si usa GUID en lugar de int como el tipo de clave principal, el valor de la clave principal del alumno no cambiará y los pasos anteriores pueden omitirse).

Ejecute el comando update-database nuevamente.

Nota : aún puede obtener un error. Durante el cambio de migración o arquitectura, si el error de migración no se puede resolver, puede continuar este tutorial cambiando la cadena de conexión web.config o eliminando la base de datos. La forma más fácil es Cambiar el nombre de la base de datos.

Prueba

Ejecute la aplicación, pruebe varias operaciones, todo se ejecuta normalmente.

En el Explorador de servidores, expanda la conexión de datos, expanda la tabla de datos SchoolContext, verá que la tabla Persona ha reemplazado las tablas Alumno e Instructor, abra la tabla Persona, verá la información anterior del alumno y el maestro.

Explorador de servidores

dbo.Person

El siguiente diagrama ilustra la estructura de la nueva base de datos:

modelos

Implementar en Windows Azure

Ligeramente ...

Resumen

Ahora implementa la herencia de tablas en cada nivel de las clases Persona, Estudiante e Instructor. Para obtener información sobre otras estructuras de herencia, vea TPH Inheritance Pattern y TPT Inheritance Pattern . En el próximo tutorial, verá cómo implementar los modos de almacenamiento y funcionamiento de la unidad.

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/69487757
Recomendado
Clasificación