AdFactum ObjectMapper .NET Blog

Official blog of the AdFactum ObjectMapper .NET

Mapping distinct classes with the same interface transparent to the application

Posted by Gerhard Stephan on June 7th, 2006

Imagine that you want to map classes that implements the same interface to database.

Example:
You want to store personal informations about an individual. The individual (you) can drive a vehicle. This vehicle is implemented as an interface and has two concrete implementations like car and motorbike. So how to map these classes?

Solution 1:
You create a property in your class that returns the interface and mark this property with the attribute [GeneralLink].

             IVehicle _vehicle;

 

            /// <summary>

            /// Gets or sets the vehicle.

            /// </summary>

            /// <value>The vehicle.</value>

            [GeneralLink]

            public IVehicle Vehicle

            {

                  get { return _vehicle; }

                  set { _vehicle = value; }

            }

This is a very easy solution that handles every object that implements the interface IVehicle. To handle the different types, the ObjectMapper .NET adds an additional column that holds information about the class name of the stored object.

CREATE TABLE [INDIVIDUAL] (

         [ID] GUID, 

         [VEHICLE] GUID,

         [VEHICLE#TYP] VARCHAR(255),

         PRIMARY KEY([ID]));

The disadvantage of that method is that you can’t add foreign keys to the database column. Why? Because it contains IDs of different tables.

Solution 2:
The second way is to implement the interface property with an [Ignore] attribute and add access properties for storing the concrete object to database.

            IVehicle _vehicle;

 

            /// <summary>

            /// Gets or sets the vehicle.

            /// </summary>

            /// <value>The vehicle.</value>

            [Ignore]

            public IVehicle Vehicle

            {

                  get { return _vehicle; }

                  set { _vehicle = value; }

            }

 

            /*

             * Access Properties used by the Object Mapper .NET

             */

 

            public Car Car

            {

                  get { return _vehicle as Car; }

                  set { if (value != null) _vehicle = value; }

            }

 

            public Motorbike Motorbike

            {

                  get { return _vehicle as Motorbike; }

                  set { if (value != null) _vehicle = value; }

            }

This is a very smart solution, because the application still uses the Vehicle Property to access the vehicle for an individual. The ObjectMapper .NET uses the concrete accessor properties to set the object. Thus enables the ObjectMapper .NET to add foreign key constraints and therefore have a better object model.

CREATE TABLE [INDIVIDUAL] (

         [ID] GUID, 

         [MOTORBIKE] GUID,

         [CAR] GUID,

        

         PRIMARY KEY([ID]));

 

ALTER TABLE [INDIVIDUAL] ADD

        CONSTRAINT INDIVIDUAL_FK01

        FOREIGN KEY ([MOTORBIKE]) REFERENCES [MOTORBIKE];

       

CREATE INDEX INDIVIDUAL_FKI01 ON [INDIVIDUAL] ([MOTORBIKE]);

 

ALTER TABLE [INDIVIDUAL] ADD

        CONSTRAINT INDIVIDUAL_FK02

        FOREIGN KEY ([CAR]) REFERENCES [CAR];

       

CREATE INDEX INDIVIDUAL_FKI02 ON [INDIVIDUAL] ([CAR]);

 

Conclusion:
If you have few derivations of the interface the second solution is much smarter because it gives you the ability to add constraints to the database and enable you to query the concrete objects. If you have many different classes that implements your interface the first solution might be better, because it does not overload your class with accessor properties.

 

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>