The original purpose of the translation and why choose the Entity Framework 6 Recipes to learn, please see the beginning of this series
2-10 Table per Hierarchy inheritance modeling
Problem
You have a database table that has a type or identification column. It can tell what the data in the row represents in your application. You want to model using table per hierarchy (TPH) inheritance mapping.
Solution Solutions
Let's say you have a 2-20 of the table (the total feeling that the author uses the diagram, and the actual description is not, such as the entity Model diagram), the employee table contains hourly employees and salaried employees rows. Column Employeetype is used as the identification column to identify the rows of the two employee types. When Employetype is 1 o'clock, this line represents a full-time employee (salaried or full-time employee) with a duty of 2 o'clock, a line of code that is an hourly (hourly employee).
Figure 2-20 Table Employee with hourly employees and salaried employees
Follow the steps below to use TPH to model table-based employee:
1. Create a context object in your project that inherits from DbContext Ef6recipescontext;
2. Use code listing 2-21 to create an abstract Poco entity employee;
Code Listing 2-21. Creating an abstract Poco entity employee
1[Table ("Employee", Schema ="Chapter2")]2 Public Abstract classEmployee {3 [Key]4 [Databasegenerated (databasegeneratedoption.identity)]5 Public intEmployeeId {Get;protected Set; }6 Public stringFirstName {Get;Set; }7 Public stringLastName {Get;Set; }8}
3. Use code listing 2-22 to create a Poco entity class Fulltimeemployee that inherits to Emplyee.
code Listing 2-22. Create a Poco entity class Fulltimeemployee
1 Public class Fulltimeemployee:employee 2 {3publicdecimalgetset;} 4 }
4. Use code listing 2-23 to create a Poco entity class Hourlyemployee that inherits to Emplyee.
code Listing 2-23. Create a Poco entity class Hourlyemployee
1 Public class Hourlyemployee:employee {2 Public decimal Get Set ; } 3 }
5. Add a property of type dbset<employee> in context.
6, in the context of the rewrite method onmodelcreating, in the method map your specific employee type to the Employeetype identification column. As shown in Listing 2-24.
code Listing 2-24. Onmodelcreating methods in the overriding context
protected override void onmodelcreating (Dbmodelbuilder modelBuilder) { base . Onmodelcreating (ModelBuilder); modelbuilder.entity <employee> (). Map <FullTimeEmployee> (m = m.requires ( employeetype ). HasValue (1 <HourlyEmployee> (m = m.requires ( " employeetype ). HasValue (2
Note: Non-shared properties (for example: salary and wage) must be nullable types.
Principle
In the table per hierarchy (usually abbreviated as TPH) inheritance map, a single table represents the entire inheritance hierarchy. Unlike tpt,tph, the base and derived classes are mixed into rows of the same table at the same time. They are differentiated according to the identification column. In our example, the authentication column is Employeetype.
In TPH, we set the mapping condition in the entity configuration to indicate the value of the discriminant column to map the table to a different derived type. We make the base class an abstract type. By setting it to an abstract type, I don't have to provide a mapping condition because an abstract entity is not created. We will never have an instance of an employee entity. We do not implement a Employeetype attribute in the employee entity. Columns are not used as mapping criteria, and are typically mapped to an attribute.
Code Listing 2-25 demonstrates inserting and fetching data from a model.
Code Listing 2-25 inserting and fetching data in our TPH model
1 using(varContext =NewEf6recipescontext ()) {2 varFTE =NewFulltimeemployee {3FirstName ="Jane",4LastName ="Doe",5Salary =71500M6 };7 context. Employees.add (FTE);8FTE =NewFulltimeemployee {9FirstName ="John",TenLastName ="Smith", OneSalary =62500M A }; - context. Employees.add (FTE); - varHourly =NewHourlyemployee { theFirstName ="Tom", -LastName ="Jones", -Wage =8.75M - }; + context. Employees.add (hourly); - context. SaveChanges (); + } A using(varContext =NewEf6recipescontext ()) { atConsole.WriteLine ("---all Employees---"); - foreach(varEmpinchcontext. Employees) { - BOOLfulltime = EMP isHourlyemployee?false:true; -Console.WriteLine ("{0} {1} ({2})", EMP. FirstName, EMP. LastName, -Fulltime?" Full time":"Hourly"); - } inConsole.WriteLine ("--- full time---"); - foreach(varFteinchContext. Employees.oftype<fulltimeemployee>()) { toConsole.WriteLine ("{0} {1}", FTE. FirstName, FTE. LastName); + } -Console.WriteLine ("---Hourly---"); the foreach(varHourlyinchContext. Employees.oftype()) { *Console.WriteLine ("{0} {1}", hourly. FirstName, hourly. LastName); $ }Panax Notoginseng}
The output of the code listing is:
---all Employees---Jane Doe, John Smith (full time),Tom Jones (Hourly)---full time---Jane Doejoh N Smith---Hourly---Tom Jones
Code listing 2-15, creating, initializing, adding two full-time employees and a hourly employee. In the query, we get all the employees, using the IS operator to determine which of the employee types we have. When I print out the employee's name, we point out his type.
In the code block, we use the generic method oftype<t> () to get full-time employees and hourly employees.
Best practices
In the TPH inheritance map, there is an argument about when to use the abstract base class and when to create a mapping condition in the entity. The difficulty of using a concrete base class is that it is tedious to query an instance of the entire inheritance. the best practice here is that if you don't need an instance of a base class entity in your app, make it an abstract type.
If you need an instance of a base class in your application, consider introducing a new inherited entity to override the mapping condition attribute in the base class. For example, in the example above we could create a derived class such as Unclassifiedemployee. Once you have this derived class, we can safely set the base class to an abstract type. This provides an easy way to circumvent the problem of querying by using the mapping condition property in the base class.
There are several guidelines to keep in mind when using TPH. 1th, the mapping condition attribute values must be independent of each other. In other words, you can't map a line to two or more types.
2nd, the mapping condition must be responsible for each row in the table, and there cannot be a row that is not mapped to the appropriate entity type. If your system is a legacy database, and the rows in the table are created by another system, you do not have the opportunity to map the condition, which can be quite troublesome. What's going to happen? rows that cannot be mapped to a base class or derived class will not be accessible to the model .
3rd, the discriminant column cannot be mapped to an entity attribute unless it is first used as a mapping condition for an IS not null. This seems a little too strict. You might ask, "If you can't set the discriminant value, how do I insert a row that represents the data for the derived class?" ", the answer is simple, you create an instance of a derived class directly, and then add it to the context as you would add another entity type instance, and the object service creates a row with an INSERT statement that has the appropriate discriminant value.
The end of this article, thank you for reading. This series by Volcanocloud translation, reproduced please indicate the source: http://www.cnblogs.com/VolcanoCloud/p/4490841.html
Entity Framework Exchange QQ Group: 458326058, welcome interested friends to join the exchange
Thank you for your continued attention, my blog address: http://www.cnblogs.com/VolcanoCloud/
Entity Framework 6 Recipes Chinese Translation Series (9)-----Chapter II The Inheritance relationship mapping based on the Entity Data Modeling TPH