This is the official Microsoft tutorial Getting Started with Entity Framework 6 Code First using MVC 5 Series. Here is Article 11th: Implement inheritance for ASP. net mvc applications
Original article: Implementing Inheritance with the Entity Framework 6 in an ASP. net mvc 5 Application
All rights reserved. The full text is not reprinted-but you can add a link to this tutorial on your website.
In the previous tutorial, you have learned how to handle concurrency exceptions. In this tutorial, we will introduce how to implement inheritance.
In object-oriented programming, you can use inheritance to reuse code. In this tutorial, you will change the aggreguctor and Student classes so that they are derived from the Person base class containing the name attributes. You do not need to change any WEB pages, but your changes are automatically reflected in the database.
Ing to database options
The aggreguctor and Student classes in the data model have the same attributes:
Suppose you want to eliminate redundant code by sharing the attributes of the instructor and student entity, or you want to write a service that correctly formats the name without worrying about whether the name comes from the student or instructor. You can create a Person base class that contains these shared attributes, and then make the class of the Teacher and Student Entity inherit from the base class, as shown in:
###
In databases, this inheritance structure has several forms. You can create a Person data table that contains information about instructors, students, and students. Some columns may only apply to instructors (employment dates), and some may only apply to students (registration dates ), use either of the two ). Generally, you have an ID column to indicate the type of each row. For example, the ID column may use "Instructor" to indicate the Instructor and "Student" to indicate the Student.
The Mode for generating an Object Inheritance structure from a single database table is called the one-Table inheritance mode at each layer.
The alternative method is to use a database that looks more like an inherited structure. For example, you can only include the attributes shared by students and instructors in the Person table and put the unique attributes in their respective tables.
Create a database table for each object class to inherit from each type of table.
However, another option is to map all non-abstract types to a single table. Attributes of all categories, including inherited attributes, are mapped to columns in the corresponding table. This mode is called the inheritance of a table of each specific class. If you implement the inheritance of a specific class-one table of the Person, Student, and uctor classes, the Student and uctor data tables are no different from what you saw before.
A table of each type and a table of each layer usually provide better performance than a table of each type in the object framework, because a table of each type may cause complex connection queries.
This tutorial demonstrates how to implement one-Table inheritance at each layer. A table on each layer is the default inheritance mode of the object framework. All you need to do is create a Person class, modify the Instructor and Student classes to derive from Person, add new classes to DbContext, and create a migration.
Create Person class
In the Models folder, use the following code to create the Person class:
Using System. componentModel. dataAnnotations; using System. componentModel. dataAnnotations. schema; namespace ContosoUniversity. models {public abstract class Person {public int ID {get; set;} [Required] [Display (Name = "last Name")] [StringLength (50)] public string LastName {get; set;} [Required] [Column ("FirstName")] [Display (Name = "Name")] [StringLength (50)] public string FirstMidName {get; set;} [Display (Name = "Full Name")] public string FullName {get {return LastName + "," + FirstMidName ;}}}}
Make Student and policuctor class inherit from Person
In the Instructor class, modify the class to derive from Person and delete the name field, as shown in the following code:
Using System; using System. collections. generic; using System. componentModel. dataAnnotations; namespace ContosoUniversity. models {public class extends uctor: Person {public int ID {get; set;} [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 {get; set ;}}}
Also modify the Student class:
Using System; using System. collections. generic; using System. componentModel. dataAnnotations; namespace ContosoUniversity. models {public class Student: Person {[Display (Name = "registration date")] [DataType (DataType. date)] [DisplayFormat (DataFormatString = "{0: yyyy-MM-dd}", ApplyFormatInEditMode = true)] public DateTime EnrollmentDate {get; set ;} public virtual ICollection <Enrollment> Enrollments {get; set ;}}}
Add the Person entity type to the model
Add the DbSet attribute of a Person object to SchoolContext. cs:
public DbSet<Person> People { get; set; }
It means all the modifications required to implement inheritance in the object framework. Later, you will see a new Person data table after the database is updated.
Create and update a migration File
On the Software Package Manager Console, enter the following command:
Add-Migration Inheritance
Then run the update-database command. The command will fail. Because the Entity Framework does not know how to migrate our existing data, the error message is similar to the following:
Open the Migrations \ <timestamp>-Inheritance. cs file and use the following code to replace the Up method:
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");}
This code executes the following database update tasks:
- The foreign key constraint and index pointing to the student data table are deleted.
- Rename the policuctor table to the Person table and modify it:
- Added EnrollmentDate that can be empty for students
- An ID column is added to indicate whether the row is a student or instructor.
- Leave the employment date blank because the student's row does not have an employment date
- Add a temporary field to update the foreign key pointing to the student. When you copy students back to the Person table, they will have a new primary key value.
- Copy data from the student table to the Person table, which causes the student to have a new primary key value.
- Fixed the foreign key value pointing to the student.
- Re-create foreign key constraints and indexes. Now they direct to the Person table
(If you use GUID instead of int as the primary key type, the primary key value of the student will not change and the above steps may be omitted .)
Run the update-database command again.
Note: You can still get an error. If the migration error cannot be resolved during migration or schema change, you can change the web. the simplest way to continue this tutorial is to rename the database.
Test
Run the application and perform various operations. Everything runs normally.
In the server resource manager, expand the data connection and expand the SchoolContext data table. You will see that the "Person" table has replaced the Student and uctor tables and opened the "Person" table, you will see information about the previous students and teachers.
The following diagram illustrates the structure of the new database:
Deploy to Windows Azure
Skip this chapter ......
Summary
Now you have implemented the inheritance of a table at each level of the Person, Student, and uctor classes. For information about other Inheritance structures, see TPH Inheritance Pattern and TPT Inheritance Pattern. In the next tutorial, you will see how to implement warehousing and unit work modes.
Author Information
Tom Dykstra-Tom Dykstra is a Senior Programmer and writer of the Microsoft Web platform and tool team.