Single Table Inheritance In LINQ To SQL

What is Single Table Inheritance?

Single table inheritance is also called filter mapping or Discriminated mapping or Table per hierarchy mapping.

With Single table inheritance, one database table is used to store the data for all the entity types in the entire inheritance hierarchy. Let’s understand with an example.

Let’s start

First, let’s create a table and insert some data in the table.

  1. Create Table SingleEmployees  
  2. (  
  3.      ID int primary key identity,  
  4.      Name nvarchar(50),  
  5.      Gender nvarchar(50),  
  6.      AnuualSalary int,  
  7.      HourlyPay int,  
  8.      HoursWorked int,  
  9.      Discriminator nvarchar(50)  
  10. )  
  11.   
  12. Insert into SingleEmployees values ('Akshay''Male', 60000, NULLNULL'PermanentEmployee')  
  13. Insert into SingleEmployees values ('Milind''Male'NULL, 50, 160, 'ContractEmployee')  
  14. Insert into SingleEmployees values ('Raghavan''Male'NULL, 40, 120, 'ContractEmployee')  
  15. Insert into SingleEmployees values ('Umesh''Male', 45000, NULLNULL'PermanentEmployee')  
  16. Insert into SingleEmployees values ('Kiran''Female', 30000, NULLNULL'PermanentEmployee')  
  17. Insert into SingleEmployees values ('Valarie''Female'NULL, 30, 140, 'ContractEmployee')  
  18.   
  19. GO   



Now, this table stores the data for both types of employees; i.e., permanent employees and contract employees. Some of the columns in this table are specific to the permanent employee

For example

Annual Salary is specific to permanent employee, which means when we insert a row of a contract employee then the column is going to be NULL.

Similarly, Hourly Pay and HourlyWorked are specific to ContractEmployee, meaning, when we insert a row for the permanent employee then those columns are going to be NULL for permanent Employee. The other columns like ID, Name and Gender are common to both the types of employees. This Discriminator column is used to distinguish between permanent employee and contract employee.

Now, when we used LINQ to SQL class designer and if we would design a class, which is based on this table, by default, LINQ to SQL is going to create one employee class.

Create an empty Application. Add a LINQ to SQL file and name it as Sample.dbml .Now, drag and drop the table to the designer


Thus, we have created one class. Now, within our organization, we had two types of employees.One is permanent employee and the other is contract employee.

Thus, we need to design class such that Employee will become the base class for us (will contain the common entities), which are shared by both of types; i.e., permanent and contract employees. Let’s see, how to design these classes.

Right click on the designer surface ->Add->Class->Change the name of the class as Permanent Employee. Add Annual Salary to permanent employee as they belong to the specific class. Similarly, add another class for ContractEmployee add HourlyWorked and Hourly Pay in Contract Employee.

Thus, our designer surface looks, as shown below.


Next step is to establish the inheritance between these classes. Now, right click on the employee class ->click Add->Inheritance. Thus, our base class is Employee and derived class is Permanent Employee. Similarly, do it for ContractEmployee.


Now, to distinguish between permanent and contract employee, we are using discriminator property. Thus, we need to set the value. Thus, right click on the inheritance relationship.


It is the discriminator, which we are using to discriminate between permanent and contract employee. Now, set the derived class discriminator as permanent employee.


Also, set inheritance, which is default as Permanent Employee.


Do the same thing for Contract Employee. Thus, we are done with designing our classes. Now, at the back-end, it has created three classes for us, which is Employee, permanent employee and contract employee.


Now, lets add a Webform to this project.


Thus, in our Webform, we got Radio button list to load all the employees, load permanent employees, and load contract employees, and we are displaying them in GridView control.

Webform1.aspx code 

  1. <html xmlns="http://www.w3.org/1999/xhtml">  
  2. <head runat="server">  
  3.     <title></title>  
  4. </head>  
  5. <body>  
  6.     <form id="form1" runat="server">  
  7. <div style="font-family: Arial">  
  8. <asp:RadioButtonList ID="RadioButtonList1" runat="server" AutoPostBack="True"  
  9.     onselectedindexchanged="RadioButtonList1_SelectedIndexChanged">  
  10.     <asp:ListItem Text="Load all Employees" Value="All"></asp:ListItem>  
  11.     <asp:ListItem Text="Load Permanent Employees" Value="Permanent">  
  12.     </asp:ListItem>  
  13.     <asp:ListItem Text="Load Contract Employees" Value="Contract">  
  14.     </asp:ListItem>  
  15. </asp:RadioButtonList>  
  16. <asp:GridView ID="GridView1" runat="server">  
  17. </asp:GridView>  
  18. </div>  
  19.     </form>  
  20. </body>  
  21. </html>   

Cs file code

  1. protected void RadioButtonList1_SelectedIndexChanged(object sender, EventArgs e)  
  2.         {  
  3.             SampleDataContext dbContext = new SampleDataContext();  
  4.             dbContext.Log = Response.Output;  
  5.   
  6.             switch (RadioButtonList1.SelectedValue)  
  7.             {  
  8.                 case "Permanent":  
  9.                     GridView1.DataSource =  
  10.                         dbContext.SingleEmployees.OfType<PermanentEmployee>().ToList();  
  11.                     GridView1.DataBind();  
  12.                     break;  
  13.   
  14.                 case "Contract":  
  15.                     GridView1.DataSource =  
  16.                         dbContext.SingleEmployees.OfType<ContractEmployee>().ToList();  
  17.                     GridView1.DataBind();  
  18.                     break;  
  19.   
  20.                 default:  
  21.                     GridView1.DataSource =  
  22.                         ConvertEmployeesForDisplay(dbContext.SingleEmployees.ToList());  
  23.                     GridView1.DataBind();  
  24.                     break;  
  25.             }   

Now, we had used a switch case here for a radio button list, when it is permanent. We want to load permanent employee for it, where we had created an instance of the sample class. Similarly, we did this for contract employees and the default value.

Now let’s run the app.


FinalOutput

As you can see from the above output, the properties that are displayed are ID, name, gender and discriminator, which are the properties present in the abstract employee class. We haven’t done employee class as abstract class to make. Click Employee class->Properties.

Select inheritance modifier as summary.


Now, let’s run the app again.


Notice, we are getting property of the requested type. Now, if we want all the columns like hourlyworked,houly pay and so on, we need to write a private method, as shown below.

  1. private DataTable ConvertEmployeesForDisplay(List<SingleEmployee> employees)  
  2.         {  
  3.             DataTable dt = new DataTable();  
  4.             dt.Columns.Add("ID");  
  5.             dt.Columns.Add("Name");  
  6.             dt.Columns.Add("Gender");  
  7.             dt.Columns.Add("AnuualSalary");  
  8.             dt.Columns.Add("HourlyPay");  
  9.             dt.Columns.Add("HoursWorked");  
  10.             dt.Columns.Add("Type");  
  11.   
  12.         foreach (SingleEmployee employee in employees)  
  13.             {  
  14.                 DataRow dr = dt.NewRow();  
  15.                 dr["ID"] = employee.ID;  
  16.                 dr["Name"] = employee.Name;  
  17.                 dr["Gender"] = employee.Gender;  
  18.   
  19.                 if (employee is PermanentEmployee)  
  20.                 {  
  21.                     dr["AnuualSalary"] = ((PermanentEmployee)employee).AnuualSalary;  
  22.                     dr["Type"] = "Permanent";  
  23.                 }  
  24.                 else  
  25.                 {  
  26.                     dr["HourlyPay"] = ((ContractEmployee)employee).HourlyPay;  
  27.                     dr["HoursWorked"] = ((ContractEmployee)employee).HoursWorked;  
  28.                     dr["Type"] = "Contract";  
  29.                 }  
  30.                 dt.Rows.Add(dr);  
  31.             }  
  32.   
  33.             return dt;  
  34.         }   

This private method is straight forward. Basically, it’s going to return a data table and we are passing the list of employees objects and its constructing a new data table. In addition to it, the data table is going to contain the respective columns and then we are using for each loop, which gets passed from the employee object, which is present.

We need to display annual salary, hourly pay, and other details of the employees only if we knownthe type of employees. Thus, we are typecasting an employee to a permanent employee. We are checking that typecasting to a permanent employee. Now, let’s run the solution.


FinalOutput1

Notice, we had all the columns here, which are specific to both permanent employees and contract employees.