Skip to main content

Inheritance Mapping

  • 3 minutes to read

When a persistent object is saved for the first time or the database schema is updated, XPO collects a list of the persistent types for the objects being persisted and creates all the necessary tables and relations between them. To mark the types you want to persist, use the PersistentAttribute and NonPersistentAttribute attributes.

By default, each persistent object type is stored in its own table with a distinctive set of columns associated with this type. The names of these tables and columns precisely resemble the type and property (field) names. This mapping behavior can be customized by applying the MapInheritanceAttribute, DbTypeAttribute and PersistentAttribute attributes.

XPO provides two general solutions for mapping inheritance into a relational database:

  • Single Table Inheritance - map the entire class hierarchy to a single table.
  • Class Table Inheritance - map each class to its own table.

These strategies are not mutually exclusive. In one hierarchy you can mix patterns. For instance, you can have several classes pulled together by a Single Table Inheritance and use Class Table Inheritance for a few specific cases. Note that this will increase the complexity.

#Map Hierarchy To A Single Table

Following this strategy you store all persistent properties and fields of a class in the same table as the properties of its parent class. In this instance, you should apply the MapInheritanceAttribute attribute to a persistent class. The attribute’s MapInheritanceAttribute.MapType property must be set to the MapInheritanceType.ParentTable value.

ORInh_Single

Single Table Inheritance

using DevExpress.Xpo;

public class Person : XPObject {
    public string Name {
        get { return fName; }
        set { SetPropertyValue(nameof(Name), ref fName, value); }
    }
    string fName = "";

}

[MapInheritance(MapInheritanceType.ParentTable)]
class Customer : Person {
    public string Preferences {
        get { return fPreferences; }
        set { SetPropertyValue(nameof(Preferences), ref fPreferences, value); }
    }
    string fPreferences = "";

}

[MapInheritance(MapInheritanceType.ParentTable)]
public class Employee : Person {
    public int Salary {
        get { return fSalary; }
        set { SetPropertyValue(nameof(Salary), ref fSalary, value); }
    }
    int fSalary = 1000;

}

[MapInheritance(MapInheritanceType.ParentTable)]
public class Executive : Employee {
    public int Bonus {
        get { return fBonus; }
        set { SetPropertyValue(nameof(Bonus), ref fBonus, value); }
    }
    int fBonus = 100;

}

Advantage: it puts all the stuff in one place, which makes modifications easier and avoids joins.

Disadvantage: large; wastes space since each row has to have columns for all possible subtypes and this leads to empty columns.

#Map Each Class To Its Own Table

This is the simplest relationship between the classes and the tables. As a result, a single table is created for each class in a hierarchy. To use this type of mapping inheritance, you should apply the MapInheritanceAttribute attribute with the MapInheritanceAttribute.MapType property set to the MapInheritanceType.OwnTable value.

ORInhEachClass

Class Table Inheritance

Disadvantage - multiple joins are needed to load a single object, which usually reduces performance.

#Member Table

#Task-Based Help

#Online Knowledge Base