Inheritance in Linq To SQL

When you are programming in .net, you can apply inheritance and polymorphism concepts on your entity classes to solve your business problems. However when you are saving those objects to the database, there is no clean way to store different child entities having some common properties that they inherit from the base class and some properties that are specific to that child entity. One of the ways to store these objects in the database is by adding all the possible fields available for all the child and base classes and marking them as allow null. Then you simply set appropriate values for only the fields that are applicable to that specific child classes. In order to differentiate each row and identity what child class it is, you can make use of discriminator column.  Let's walk through an example to get a clear understanding of how to structure your inheritance hierarchy in the database.

image

In the above code, I have a table called worker which contains different type of Worker. All workers basically inherit from a base class called Worker. The base class for the worker has one property called Name which every derived class inherits. Every derived class has some properties that are specific to that class itself. For Example the first record with Alvin is Salaried Worker which has a property of FixedSalary.  Keven worker is an Hourly Worker which uses Hourly Rate and Hours column. Jack is a commission worker that uses commissionperc and WidgetSold column to get its salary. Tony is a SalariedBonus Worker which uses Fixed Salary column and a bonus column to determine its salary.

Now that you have seen how these rows are defined in the table, the question becomes how do we map these different type of records to different entities and map their specific columns to properties on the derived classes. Linq to SQL allows child classes derived from the same base class to map to the same table in the database. You basically use Inheritance attribute on your base class to define different derived entities having different value for the discriminator column. The Code parameter specifies the specific value for that discriminator column that would map that record to the entity specified in the Type attribute. Below is an example of how I am mapping my table to entities defined using Linq to SQL attributes to map my records to different derived entities.

image

In order to set up my inheritance on my derived classes, I first define Type property on my worker which determines what type of object to instantiate for a particular record in the database. Next I specify all the inheritance mappings to all the derived classes based on the a specific valued found in the discriminator column by making use of Code attribute. Since my worker class is defined as abstract, Linq to SQL cannot instantiate Worker class. Hence I have to define the default mapping to use in the case if the record in the database defines no value for Type column. In my case I have specified to create an instance of SalariedWorker when the type attribute is missing in the database. Also notice that each derived classes have their own specific properties are related to that derived class. I am also providing an abstract method called GetSalary. Each derived entity overrides the GetSalary method, and using its properties calculates the appropriate salary based on its type.

Once I have configured my classes, we will see how to query for our derived classes using Linq syntax and how to insert derived entities in the Worker table. Below is the code that shows how to accomplish that.

image

image

In the first query I am getting a collection of workers and printing their name,type and salary. Because of my inheritance mapping my workers collection consists of different derived entities. However I use the base class reference to get the salary of each worker. Since every derived class overrides the method, they get to specify how to get the salary for their type using polymorphism.

In the second query I am simply getting the first worker who is salaried worker. In the background Linq to SQL generates query against worker table with type filter of Salaried Worker. The third query uses is operator to only retrieve the worker of type CommissionWorker. The query is not any different from our previous query. Only difference is, when you use OfType operator you get a strongly typed derived class where as when  you use is operator you get the derived object but its uses base class reference. Therefore in my code when I had to access specific property on the Commission Worker, I had to the cast Worker object to commission worker to access properties specific to commission worker.

In the last portion of my code, I create an an array of two different types of derived entities and specify their respective property values. I am than persisting those objects inside the database. Output below confirms that our record got inserted in the database along with its type discriminator column.

image

4 Comments

  • hi, can we use interface instead of abstract class?

  • thank -- exactly the walkthrough i was looking for... datacontext.base.oftype was the missing link

  • How the inherited table type can be passed as a method parameter? In other words, if I want to insert into Worker table first entries of SalariedWorker type, and then entries of HourlyWorker type, I would need to define method like:

    private void InsertIntoWorker(IQueryable theTable)
    {
    var newEntry = new typeof (theTable) { Name = “NewWorker”};
    db.Workers.InsertOnSubmit(newEntry);
    db.SubmitChanges();
    }

    And then call this method for SalariedWorker and for HourlyWorker:
    InsertIntoWorker(db. SalariedWorker);
    InsertIntoWorker(db. HourlyWorker);

    Of course, this doesn’t compile. What would be the way to accomplish this?

  • All the null's in the DB seem to be a waste. Is there a way to accomplish the same thing without having all those null's?

Comments have been disabled for this content.