Mapping inheritance allows you to extend an existing mapping. This can be extremely powerful when dealing with inheritance trees and removes the need for duplication of effort.
Let's take a simple example using the Northwind Products table. While developing our application, we've come to realize that we have two different Product implementations: ProductInfo, which is focused on high-level product information, and ProductDetails, which extends ProductInfo with additional information. Behind the scenes, both of these classes map to the Products table. But, from an OOP perspective, they're two distinct classes with an inheritance chain.
First, let's create our two classes:
using System;
using Adapdev.Text;
using Elementary.Attributes;
namespace Elementary.Northwind.Samples.Attributes.MappingInheritance
{
[ElementaryClass(Table="Products")]
public class ProductInfo
{
[Persist] public int CategoryID = 0;
[Persist] public int ProductID = 0;
[Persist] public string ProductName = "";
[Persist] public int SupplierID = 0;
public override string ToString()
{
return StringUtil.ToString(this);
}
}
public class ProductDetail : ProductInfo
{
[Persist] public string QuantityPerUnit = String.Empty;
[Persist] public double UnitPrice = 0.00;
[Persist] public int UnitsInStock = 0;
[Persist] public int UnitsOnOrder = 0;
[Persist] public int ReorderLevel = 0;
[Persist] public int Discontinued = 0;
}
/// <summary>
/// Test to validate that table names are automatically inferred
/// </summary>
[ElementaryClass]
public class Products
{
[Persist]
public int CategoryID = 0;
[Persist]
public int ProductID = 0;
[Persist]
public string ProductName = "";
[Persist]
public int SupplierID = 0;
public override string ToString()
{
return StringUtil.ToString(this);
}
}
}
As you can see, ProductDetail inherits from ProductInfo.
With this simple extension, we can now work with both objects and persist them to the same database table. First, let's create a test to get all ProductInfo objects:
using System;
using System.Collections.Generic;
using System.Transactions;
using Elementary;
using Elementary.Northwind.Samples;
using NUnit.Framework;
namespace Elementary.Northwind.Samples.Attributes.MappingInheritance
{
/// <summary>
/// Summary description for Test.
/// </summary>
[TestFixture]
public class Test
{
[TestFixtureSetUp]
public void SetUp()
{
Elementary.Clear();
Elementary.LoadAssembly("Elementary.Northwind.Samples.dll");
}
[Test]
public void GetProductInfoCollection()
{
IObjectMapper<ProductInfo> mapper = Elementary.GetIObjectMapper<ProductInfo>();
IList<ProductInfo> al = mapper.GetCollection();
Assert.IsTrue(al.Count > 0, "No products loaded.");
Assert.AreEqual(77, al.Count, "Not all products were loaded.");
Console.WriteLine("Loaded {0} products.", al.Count);
Console.WriteLine("\nFirst product:\n{0}", al[0]);
}
}
}This gives us the following output:
Loaded 77 products. First product: Properties for: ProductInfo CategoryID(System.Int32): 1 ProductID(System.Int32): 1 ProductName(System.String): Chai SupplierID(System.Int32): 1
If we do the same thing for ProductDetail, we'll receive the same number of records, but the additional properties will be populated:
[Test]
public void GetProductDetailCollection()
{
// Retrieves the mapping via object type
// Elementary looks at the full object name and locates the corresponding node in the mappings file
IObjectMapper<ProductDetail> mapper = Elementary.GetIObjectMapper<ProductDetail>();
IList<ProductDetail> al = mapper.GetCollection();
Assert.IsTrue(al.Count > 0, "No products loaded.");
Assert.AreEqual(77, al.Count, "Not all products were loaded.");
Console.WriteLine("Loaded {0} products.", al.Count);
Console.WriteLine("\nFirst product:\n{0}", al[0]);
}
Output:
Loaded 77 products. First product: Properties for: ProductDetail QuantityPerUnit(System.String): 10 boxes x 20 bags UnitPrice(System.Double): 0 UnitsInStock(System.Int32): 39 UnitsOnOrder(System.Int32): 0 ReorderLevel(System.Int32): 10 Discontinued(System.Int32): 0 CategoryID(System.Int32): 1 ProductID(System.Int32): 1 ProductName(System.String): Chai SupplierID(System.Int32): 1
You can also save, update, query, etc. and the same behaviors will occur - two separate objects mapped against one specific table. For more in-depth samples, look at the MappingInhertiance examples.