Telerik OpenAccess Classic

Telerik OpenAccess ORM Send comments on this topic.
How to: Define a Model with Flat Mapping
Programmer's Guide > OpenAccess ORM Classic (Old API) > OpenAccess Tasks > Defining a Data Model > How to: Define a Model with Flat Mapping

Glossary Item Box

This documentation article is a legacy resource describing the functionality of the deprecated OpenAccess Classic only. The contemporary documentation of Telerik OpenAccess ORM is available here.

Flat mapping uses only one table and fields from the subclasses are mapped to the superclass table. It requires the addition of a discriminator or indicator column to the table for the base class to identify the type of each row (except for one special case which has been described below). Flat mapping is the simplest and is usually the fastest option.

 

Advantages of flat mapping are:

  • Only a single query is required to retrieve all of the instances in a hierarchy without any extra joins
  • Creating, updating or deleting an instance requires only a single INSERT, UPDATE or DELETE statement

 

Disadvantages of flat mapping are:

  • The base table has many columns that may be used by only a few subclass instances
  • A discriminator or class indicator column is required to identify the type of each row

 

Because flat mapping is the default model used by Telerik OpenAccess ORM, there are no additional actions required to achieve it except persisting the classes. While the project is being built, the following table is created:

  

When only certain subclasses are required, the generated SQL uses the discriminator column to filter the results. Here is an example:

OQL

Copy Code
SELECT * FROM DogExtent

The values in the WHERE clause IN list are the default db-class-id values for Dog, WeinerDog and Rottweiler:

SQL Copy Code
SELECT pet_id, voa_class, best_friend, nme, voa_version,
       cats_eaten, lngth
 
FROM pet
   
WHERE voa_class IN (759263421,1302943882,958541839)

The discriminator column is normally mapped to a SQL INTEGER, if all of the discriminator values are int values. But, if any one class in the hierarchy has a ClassID other than an integer then the discriminator column will be mapped to a SQL VARCHAR. However, this can be changed using the db-class-id extension in the metadata. The discriminator column has the name ‘voa_class’ by default and its type is a 32-bit positive hash of the fully qualified class name. This value can be changed with another or even can be removed if flat mapping without a discriminator column is required. In the Forward Mapping wizard can be noticed that mapping strategy for all subclasses is set to ‘flat’. These are the default settings.

Flat mapping with no discriminator


Normally a discriminator column is required for flat inheritance. However if each class in the hierarchy has at the most one subclass, then the discriminator can be disabled and all the rows are considered instances of the leaf class of the hierarchy. A UserException is thrown on any attempt to persist a non-leaf-class instance.
In the example flat mapping without a discriminator column could be used if we had only the ‘Pet’, ‘Dog’ and ‘Rottweiler’ classes or any other hierarchy that has no more than one child class per parent. Configuration is made in the Forward Mapping wizard by selecting the {no} option in the Discriminator Value combo box for the top class (in the example this is ‘Pet’).

As a result the following table is created:

Discriminator Column

The discriminator column used to identify the type of each row with flat mapping (and, optionally, for vertical mapping) is normally mapped to a SQL INTEGER but can be changed using the db-class-id extension. The default class-id value for a class is a 32-bit positive hash of the fully qualified class name but this can also be changed by using the db-class-id extension.  

If you are using the default class-id values, you need to be careful if you change the name or namespace of a class in a hierarchy. The automatically generated class-ids used in the discriminator column will change and this will invalidate the existing data. You can either specify the old class-id as shown in the following example (See db-class-id) or update the table.

The name of the discriminator column can be changed as well. It should be set in the db-column-name extension of the db-column node.

The following example maps the class-id column to a TINYINT and specifies the column name and new class-id values that will fit into a byte field:

App.config

Copy Code
...
<mapping>
 
<namespace name="Inheritance.Model">
   
<class name="Cat" >
     
<extension key="db-class-id" value="12" />
   
</class>
   
<class name="Dog">
     
<extension key="db-class-id" value="4" />
   
</class>
   
<class name="Pet">
     
<extension key="db-class-id" value="8">
       
<extension key="db-column">
         
<extension key="db-type" value="TINYINT" />
         
<extension key="db-column-name" value="ClassType" />
       
</extension>
     
</extension>
   
</class>
   
<class name="Rottweiler">
     
<extension key="db-class-id" value="6" />
   
</class>
   
<class name="WienerDog">
     
<extension key="db-class-id" value="2" />
   
</class>
 
</namespace>
</
mapping>
...
Note that if you want to base your class hierarchy on an existing table by using reverse mapping, the discriminator column should not be mapped to any class field! The "Map column" check box in the Reverse mapping wizard should be disabled. Operations on the discriminator column are done internally. Just make sure you have specified the correct column name in the configuration file as shown above.