Using the Domain Objects Persistence Pattern in .NET

Domain application objects are usually central to the entire application and used by most subsystems. They represent the core data and business validation rules; therefore, good domain object design is critical for robust, high performing, yet flexible applications.

by Iqbal M. Khan

Aug 24, 2005

Page 1 of 2

hen developing object-oriented applications that use relational databases, creating a domain object design that's consistent with the database design makes applications easier to understand, because domain objects typically represent real-life "entities" and their relationships with each other. Therefore, in many situations, the domain objects are "mapped" to the relational database tables and relationships between tables. However, it is very easy to get this mapping wrong and end up with an undesirable domain object design. A good design for domain objects requires developers to have a solid understanding of object oriented and relational fundamentals.
The Domain Objects Persistence pattern attempts to provide a mapping to relational databases that decouples the domain objects from the persistence logic. In this pattern, the domain objects themselves are unaware of the persistence mechanism, because the dependency is only one-way (from persistence objects to domain objects). This simplifies the domain objects' design and makes them easier to understand. It also hides the persistence objects from other subsystems in the application that are using the domain objects. Even better, the pattern also works in distributed systems where only the domain objects are passed around, thus insulating the application from exposing the persistance mechanism to outside code. This article shows you how to incorporate the Factory pattern into the Domain Objects Persistence pattern to help decouple domain objects and persistence logic.

Defining the Problem
Domain objects form the backbone of any application. They capture the core data model from the database and the business rules that apply to that data. Typically, most subsystems of an application rely on these common domain objectsmeaning that the more closely the domain objects map to the database schema, the easier it is for application developers to understand and use them because they mimic the real-life "entities" and "relationships" represented in the database.
When domain objects are not separated from the rest of the application, you often end up with duplicated persistence code in multiple locations. Similarly, when domain objects are not separated from the persistence code, you'll face situations where any subsystem using the domain objects must also know and depend on the persistence objects. Any change in persistence objects necessarily affects the entire application; hence, failing to separate domain objects from the application and the persistence code is a bad design.

Defining a Solution
One way to achieve the above-mentioned goals is to separate the domain objects into a separate subsystem and let the rest of the application use them whenever it needs domain data. Additionally, you should separate domain objects from the persistence code. On one hand, this double-decoupling avoids code duplication, and on the other it hides the persistence details from the domain objects, creating a flexible design that's easier to change. The domain objects and the rest of the application are totally unaffected whether the data comes from a relational database, an XML file, a flat file, Active Directory/LDAP, or any other source.
In separating persistence logic from domain objects, you must ensure that the domain objects have no dependency on the persistence code. Doing that allows you to expose the domain objects even in environments where you don't want to expose the persistence code.