Speaking about the flexibility of persistent model mapping, DataObjects.Net v3 had the following restrictions:
- There was exactly one hierarchy with root in DataObject class.
- Structure of identity field and type discriminator field was explicitly defined in DataObject class.
- Only one inheritance mapping scheme -- Class Table Inheritance (with some minor exceptions) was supported.
- Top-down development model was used. You create persistent classes, database schema is generated automatically.
Look how classic business model (Customer, Product, Order & OrderItem objects plus 2 lookup objects: DeliveryMethod & Category) might be implemented in DataObjects.Net v3:
DataObject class was the root of all. It provided identity field (type of long) and type discriminator (type of int). Developer didn’t have the possibility to define his own identity field(s) as well as custom identity provider(s), to use his own type discriminator or to choose another inheritance mapping scheme.
But I’m not going to say that it was absolutely bad or not – it really depends on concrete project. For the majority of small or medium-sized projects (startups -- DataObjects.Net v3 niche) these restrictions don’t matter at all and even make life of developer a bit easier (you don’t have to think about entity identifiers, type discriminators, hierarchy mappings and identity providers – just create your business model and let DataObjects.Net make the rest).
Time goes by, DataObjects.Net grew up and what was good for startups is not always good for large and complex projects. First of all, I mean that Bottom-up development model (mapping of existing database schema to persistent classes) must be supported as well. To achieve the goal we made the following modifications to persistent model mapping architecture:
- Conception of “Hierarchy” was introduced. It represents a set of persistent classes that inherit an hierarchy root where identity fields are explicitly defined. All members of hierarchy share identity fields, inheritance mapping scheme, identity provider and type discriminator, if any. Hierarchy can contain one or more members, hierarchy depth is unrestricted. Number of hierarchies within Domain model is also unrestricted. The only restriction is that member of one hierarchy can’t belong to another hierarchy.
- Class “Key” was introduced, it represents a set of identity fields. Every hierarchy defines its own Key structure and every Entity instance is identified by Key instance. Number of fields in Key is unrestricted, the only restriction is fields type: only primitive types can be used, plus strings.
- In the nearest future custom type discriminators will be also supported.
Let’s update the sample persistent model, using new features of DataObjects.Net v4.
As you see, with DataObjects.Net v4 we got three independent hierarchies in the sample model:
- Hierarchy with root in BusinessObject with identity field type of long.
- Hierarchy with root in LookupObject with identity field type of int. This hierarchy is a good candidate for Single Table Inheritance mapping scheme.
- Hierarchy with root in OrderItem with composite primary key (contains references to Order & Product, both type of long).
Entity type (former DataObject) doesn’t define structure of identity fields anymore. Instead, every hierarchy root defines its own Key structure. Entity class just contains the Key field where identity fields are automatically aggregated in form of Tuple. Also note, that type discriminator (TypeId field) still resides in Entity class (this will be refactored soon).
Thus, DataObjects.Net v4 now is much more closer to Bottom-up development model support then ever.