[
Advertise | Submit Code | About us | Contact us | Link us
]
Go!
Membership Services
Login
Register

Home
C# General

General

C# Language

Design & Architecture

Algorithms

Database

Security

Active Directory

COM Interop

Remoting
C# Windows Forms

General

Combo and List boxes

Miscellaneous Controls

Button Controls

Edit Controls
Cutting Edge

ASP.NET 2.0

Visual Studio 2005

Windows Longhorn

SQL Server 2005
C# Multimedia and GDI+

General

DirectX

GDI+

Audio
Internet & Web

General

Images and multimedia

Database

Utilities

Security

ASP.NET Controls

Design and Architecture

Webservices
.NET

General

Design & Architecture

Algorithms

Database

Security

Active Directory

COM Interop

Remoting

ADO.NET

XML.NET

Tools

Enterprise

IDE
Visual Basic .NET

VB.NET General

VB.NET Controls
General Reading

.NET Books Review

Product Showcase

Book Chapters

Business Design & Strategy
Community

Discuss

Job Board

Discussion

CodeXchange
DeveloperLand

Advertise

Submit Code

About us

Contact us

Link us
Miscellaneous

Favorite Links

Downloads

Programming Sites

Top Stories
Regular Expressions

E-Mail

Date/Time
Home > C# General > Database
Domain Objects Persistence Pattern for .NET
Posted by on Wednesday, July 13, 2005 (EST)

Domain objects in an application represent the core data and business validation rules relating to it.Therefore, their good design is critical for a good application design that is robust, high performing, and yet flexible.

This article has been viewed: 5,547 times
Technology: Database.

Contents

Domain Objects Persistence Pattern for .NET

Top Go to Table of Contents

Abstract

Domain objects in an application represent the core data and business validation rules relating to it. And, domain objects are usually central to the entire application and used by most subsystems. Therefore, their good design is critical for a good application design that is robust, high performing, and yet flexible.

When it comes to developing object oriented applications that use relational databases, the domain object design has to be consistent with the database design. This make them easier to understand because they 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 a solid understanding of object oriented and relational fundamentals on the part of developers.

Domain Objects Persistence Pattern attempts to provide a solution for domain object mapping to the relational databases that decouples the domain objects from the persistence logic. The domain objects in this pattern are unaware of the objects that persist them because the dependency is only one-way (from persistence objects to domain objects). This makes the domain objects design much simpler and easier to understand. It also hides the persistence objects from other subsystems in the application that are using the domain objects. This also works in distributed systems where only the domain objects are passed around. In this context, an attempt is made to incorporate the Factory Pattern into this pattern to help decouple domain objects and persistence logic.

Top Go to Table of Contents

Scope

Domain Objects, Persisting Domain Objects.

Top Go to Table of Contents

Problem Definition

Domain objects form the backbone of any application. They capture the core data model from the database and also the business rules that apply to this data. It is very typical for most subsystems of an application to rely on these common domain objects. This means that the closer the domain objects map to the data model in the database, the easier it is for the application developers to understand and use them because they mimic real-life "entities" and "relationships" as represented in the database.

If domain objects are not separated from the rest of the application, we end up with duplication of code everywhere. Similarly, if domain objects are not separated from the persistence code, we face situations where any subsystem using the domain objects also knows and depends on the persistence objects. And, any change in persistence objects affects the entire application, hence a bad design.

Top Go to Table of Contents

Solution

One way to achieve the above mentioned goals is to separate the domain objects into a separate subsystem and let the entire application use them wherever it needs domain data. Additionally, we should separate domain objects from the persistence code. This double-decoupling allows us on one hand to avoid code duplication and on the other to hide the persistence details from the domain objects and make it more flexible in case it needs to change. The domain objects and the rest of the application is totally unaffected whether the data is coming from a relational database or any other source (e.g. XML, flat files, or Active Directory/LDAP).

In separating the persistence logic from domain objects, we ensure that the domain objects have no dependency on the persistence code. This allows the domain objects to become available in environments where we don't even want to expose our persistence code.

Sample Code

In this sample, we will look at a Customer object from Northwind database mapped to the "Customers" table in the database.

public class Customer {
    // Private data members
    String      _customerId;
    String      _companyName;
    String      _contactName;
    String      _contactTitle;
    public Customer() {}
    // Properties for Customer object
    public String CustomerId {
        get { return _customerId; } set { _customerId = value;}
    }
    public String CompanyName {
        get { return _companyName; } set { _companyName = value;}
    }
    public String ContactName {
        get { return _contactName; } set { _contactName = value;}
    }
    public String ContactTitle {
        get { return _contactTitle; } set { _contactTitle = value;}
    }
}
public interface ICustomerFactory 
{
    // Standard transactional methods for single-row operations
    void Load(Customer cust);
    void Insert(Customer cust);
    void Update(Customer cust);
    void Delete(Customer cust);
    // Query method to return a collection
    ArrayList FindCustomersByState(String state);
}
public class CustomerFactory : ICustomerFactory
{
    // Standard transactional methods for single-row operations
    void Load(Customer cust) { /* Implement here */ }
    void Insert(Customer cust) { /* Implement here */ }
    void Update(Customer cust) { /* Implement here */ }
    void Delete(Customer cust) { /* Implement here */ }
    // Query method to return a collection
    ArrayList FindCustomersByState(String state) { /* Implement here */ }
}

Below is an example of how a client application will use this code.

    public class NorthwindApp
    {
        static void Main (string[] args) {
            Customer cust = new Customer();
            CustomerFactory custFactory = new CustomerFactory();
            // Let's load a customer from Northwind database.
            cust.CustomerId = "ALFKI";
            custFactory.load(cust);
            // Pass on the Customer object
            FooBar(cust);
            // custList is a collection of Customer objects             
            ArrayList custList = custFactory.FindCustomersByState("CA");
         }
    }
As you can see above, the "load" method loads the Customer object from the database based on the CustomerId. Once the Customer is loaded, then it can be passed on to any subsystem in the application without exposing the persistence code. Similarly, if you get an ArrayList of Customer objects, you can pass on the ArrayList which has no persistence code dependency.

Top Go to Table of Contents

Conclusion

Using the Domain Objects Persistence pattern, we have extracted the persistence code out of the Customer object. This has made Customer object more object-oriented and simpler to understand because its object model is closer to the data model in the database. And, finally, we have enabled the Customer object to be passed around to different parts of the application (or even to distributed applications through .NET Remoting) without exposing its persistence code.

Author: Iqbal M. Khan works for AlachiSoft, a leading software company providing O/R Mapping and Clustered Object Caching solutions for .NET. You can reach him at iqbal@alachisoft.com [^] or visit Alachisoft at www.alachisoft.com [^].

Top Go to Table of Contents

About Iqbal Khan

Iqbal Khan is the Director Sales & Marketing at AlachiSoft (http://www.alachisoft.com), a leading provider of O/R Mapping tool called TierDeveloper. You can reach him at iqbal@alachisoft.com.

Click here if you want to know more about .

Other articles that may interest you

  • Write a Word Add-In – Part 0
  • Write a Word Add-In – Part I
  • Lengthy Operations on Single Thread in .NET Application
  • Learning Draughts
  • Exceptions and Performance
  • Average Rating :

    Discussion Forums
    Got a programming related question? Hopefully someone has the answer... Want to help out other developers? Visit our discussion forums.

    Sponsored by:

    New Articles

  • Exceptions and Performance
    Almost every time exceptions are mentioned in mailing lists and newsgroups, people say they're really expensive.Let's examine that claim, shall we?

  • Creating multilingual websites - Part 1
    Extend the existing globalization capabilities of .NET to create flexible and powerful multilingual web sites. First, create a custom ResourceManager, and then create custom localized-capable server controls to easily deploy multilingual functionality.

  • Parameter passing in C#
    Many people have become fairly confused about how parameters are passed in C#, particularly with regard to reference types. This page should help to clear up some of that confusion

  • Most Popular Articles

  • LDAP, IIS and WinNT Directory Services
    This article explains how to use .NET Directory Services to retrieve and search directory objects, create new directory objects and edit or delete existing directory objects. Describes Active Directory Application Mode (ADAM) and how to use the IIS, WinNT and LDAP directory (ADSI) provider.

  • An in-depth look at WMI and instrumentation, Part II
    WMI stands for Windows Management Instrumentation and, as the name indicates, is about managing your IT infrastructure this article is the second part of a two-part series.

  • An in-depth look at WMI and instrumentation, Part I
    WMI stands for Windows Management Instrumentation and, as the name indicates, is about managing your IT infrastructure this article provides an in-depth look at WMI and MOM 2005

  • New Books

  • Murach's ASP.NET 2.0 Upgrader's Guide: VB Edition
    What’s new and how to use it! That’s what this book delivers if you’re a VB developer who’s interested in upgrading from ASP.NET 1.x to ASP.NET 2.0.

  • C# in easy steps
    Learn to program with Microsoft’s premier programming language. No previous programming knowledge is assumed. With numerous easy-to-follow examples, this title explains the essentials of object-oriented programming with C#.

  • Murach's ASP.NET web programming with VB.NET
    Murach's ASP.NET web programming with VB.NET by Doug Lowe and Anne Prince is a in depth training and reference book for ASP.NET programming using VB.NET. The book builds upon Murach's previous books and covers more advanced concepts for programming ASP.NET pages.

  • Got Code?

    if you have any article , source code , or anything else you'd like to share with this community that you think others might find useful, please submit it here and we will gladly make it available on this site. submit@developerland.com.
    Partners

    All articles are copyrighted by their individual authors unless otherwise specified , everything else Copyright ©2004-2006 DeveloperLand