Click here to Skip to main content
15,867,308 members
Articles / Web Development / ASP.NET

Web Service via Data Access Object Pattern

Rate me:
Please Sign up or sign in to vote.
3.89/5 (16 votes)
9 Oct 2007CPOL4 min read 96.3K   869   73   11
A Data Access Object pattern implementation

Introduction

Access to the data source varies depending on the source of data. Access to persistent storage, such as to a database, varies greatly depending on the type of storage and vendor implementation. The ODBC API enables applications to use SQL statements. However, even within RDBMS environments, the actual syntax and format of SQL statements vary depending on the particular database product. There is even greater variation with different types of persistent storage. Access mechanism, supported APIs, and features vary between different types of persistent storage, such as RDBMS, object-oriented databases, LDAP, flat file, XML file, and so forth. Such disparate data sources make challenges to applications, and can potentially create a direct dependency between the application and the data source code. When business components need to access a data source, they use the appropriate APIs to create connectivity and manipulate the data source. But including the data access code within business components introduces a tight coupling between the business components and the data source implementation. Such code dependencies make it difficult to migrate from one type of data source to another. When the data source changes, the business components have to be changed to handle the new type of data source.

Solution

Use the Data Access Object to do all manipulations to the data source object. The DAO manages the connection with the data source to get and store data. The DAO implements all access functionality to work with the data source. It doesn't matter what the data source is. It could be any persistent storage such as RDBMS, a repository like LDAP, or even just XML files. The business components that rely on DAO use a simple interface exposed by DAO to its clients. The DAO doesn't show the data source implementation and there is no need to do this. Because the DAO interface doesn't need to change when the underlying data source changes, this ability allows DAO to adapt to different types of storage without having to handle it within the business component. You can also say that the DAO acts as an adapter between the components and the data source object.

Picture 1. Relationships in the DAO pattern
       ------------------   uses          -------------------   encapsulates    -----------
      |   BusinessObject | ------------> |  DataAccessObject | --------------> | DataSource | 
       ------------------                 -------------------                   ------------
                         \                 /
                          \               /
                           \             /  
obtains, modifies, and      \           / save the transfer object into  
creates the transfer object  \         /  persistent data storage
                              \       /
                               \     /
                                \   /
                                \/ \/
                           -----------------
                          |  TransferObject |
                           ----------------- 

Business Object

This object represents the data client. It's the object that requires access to the data source to obtain and modify the data.

Data Access Object

This object is the underlying object in this pattern. It abstracts the data access implementation for its clients to enable transparent access to the data source. The business object delegates the data creation and stores actions to the data access object.

Data Source

This object represents a data source implementation. It could be any persistent storage, for instance, RDBMS, OODBMS, XML repository, flat file system, and so forth.

Transfer Object

This object represents a data carrier. The data access object uses this object to return the data to the client as well as to receive updates and create the data in the data source.

Sample Project

I provided this sample project with two kinds of DAO: XmlRepository and MSSql. This sample project demonstrates how easy it is to use this pattern. It also shows that any migration from one data source to another is a piece of cake.

Screenshot - Diagram.jpg

As you can see, I use the abstract factory model. DaoFactory is the abstract class for all DAO factories.

C#
public abstract class DaoFactory 
{
    public abstract  CustomerDao  GetCustomerDao();
    public abstract  OrderDao   GetOrderDao();
       
    public static DaoFactory GetDaoFactory()
    {
        string strDaoFactoryType = ConfigurationManager.AppSettings["DaoFactory"];
        if (String.IsNullOrEmpty(strDaoFactoryType))
            throw new NullReferenceException("DaoFactory type configuration " + 
                                             "is missing from your web.config.");

        else
        {
            Type DaoFactoryType = Type.GetType(strDaoFactoryType);
            if (DaoFactoryType == null)
                throw new NullReferenceException("DaoFactory type can not be found.");

            Type DaoFactoryBaseType = 
                 Type.GetType("AndrewGolik.DaoTraining.DataAccessLayer.DaoFactory");
            if (!DaoFactoryBaseType.IsAssignableFrom(DaoFactoryType))
                throw new ArgumentException("DaoFactory type does not inherits " + 
                          "from AndrewGolik.DaoTraining.DataAccessLayer.DaoFactory.");

            DaoFactory daoFactory = (DaoFactory)Activator.CreateInstance(DaoFactoryType);
            return daoFactory;
        }
    }
}

The implementation of MSSqlDaoFactory:

C#
public class MSSqlDaoFactory:DaoFactory
{
    public static string ConnectionString
    {
        get
        {
            if (ConfigurationManager.ConnectionStrings["MsSqlDao"] == null)
                throw new NullReferenceException("MsSqlDao connectionString " + 
                          "configuration is missing from your web.config.");
            string connectionString = 
                   ConfigurationManager.ConnectionStrings["MsSqlDao"].ConnectionString;
            if (String.IsNullOrEmpty(connectionString))
                throw new NullReferenceException("MsSqlDao connectionString " + 
                          "configuration is missing from your web.config.");
            else
                return connectionString;
        }
    }
    public override CustomerDao GetCustomerDao() 
    {
       return new MSSqlCustomerDao();
    }
    public override OrderDao GetOrderDao() 
    {
        return new MSSqlOrderDao();
    }
}

The implementation for XmlDaoFactory is the same, except specific changes. XmlDaoFactory doesn't have the connection string, but it has paths to XML files.

C#
public class XmlDaoFactory:DaoFactory
{
    public static string PathToCustomersFile
    {
       get{
         string pathToFile = HttpContext.Current.Server.MapPath(
                                "App_Data/XmlRepository/Customers.xml");
         if (!File.Exists(pathToFile))
         {
             XmlDocument xmlDoc = new XmlDocument();
             xmlDoc.LoadXml("<customers lastgeneratedid="\"0\"">");
             xmlDoc.Save(pathToFile);
         }
         return pathToFile;
       }
    }
    public static string PathToOrdersFile 
    {
        get
        {
            string pathToFile = HttpContext.Current.Server.MapPath(
                                  "App_Data/XmlRepository/Orders.xml");
            if (!File.Exists(pathToFile))
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml("<orders lastgeneratedid="\"0\"">");
                xmlDoc.Save(pathToFile);
            }
            return pathToFile;
        }
    }
    public override  CustomerDao  GetCustomerDao()
    {
         return new XmlCustomerDao();
    }
    public override OrderDao GetOrderDao() 
    {
        return new XmlOrderDao();
    }
}

There are only two business objects in this project: Customer and Order. So we need to have two interfaces: CustomerDao and OrderDao.

C#
public interface OrderDao
{
    int CreateOrder(Order order);
    bool DeleteOrder(int orderID);
    bool UpdateOrder(Order order);
    List<order> GetOrders();
}

public interface CustomerDao
{
     int CreateCustomer(Customer customer);
     bool DeleteCustomer(int customerID);
     bool UpdateCustomer(Customer customer);
     List<customer> GetCustomers();
     bool DeleteOrders(int customerID);
}

These interfaces describe the base data access functionality for all DAO implementations. Once you add a new interface method, you have to modify all DAO implementations of the interface.

The implementation of OrderDao:

C#
public class MSSqlOrderDao:OrderDao
{
    public int CreateOrder(Order order)
    {
        //using the Transact-SQL 
        //return the order id on success  
        ......
    }
    public bool DeleteOrder(int orderID) 
    {
       //using the Transact-SQL 
       //return the true if the order is removed, otherwise false
        .......
    }
        
    public bool UpdateOrder(Order order) 
    {
       //using the Transact-SQL 
       //return the true if the order is removed, otherwise false
        .......
    }

    public List<order> GetOrders() 
    {
       //using the Transact-SQL 
       //return the list of orders
        .......
    }
}

The implementation of XmlOrderDao is specific because it uses XML files to store the data.

The transfer objects are used by DAO to send and receive data from the data client.

C#
public class Customer
{
    private const int defaultIDValue = 0; 
    private int _customerID;
     private string _companyName; 
    private string _contactName; 
    private string _contactTitle; 
    private string _address; 
    private string _city;  
    private string _region; 
    private string _postalCode; 
    private string _country;  
    private string _phone; 
    private string _fax;

    //get and set properties.....
}
public class Order
{
    private const int defaultIDValue = 0; 
    private int _orderID;
    private int _customerID;
    private DateTime _orderDate;
    private Decimal  _freight;
    private    string _shipName;
    private string _shipAddress;
    private string _shipCity;
    private string _shipRegion;
    private string _shipPostalCode;
    private string _shipCountry;
    
    //get and set properties.....

It's pretty simple to use DAO from the data client.

C#
[WebMethod]
public bool UpdateCustomer(int customerID ,string companyName, string contactName,
                string contactTitle, string address, string city, string region,
                string postalCode, string country, string phone, string fax)
{

    Customer customer = new Customer(customerID , companyName, contactName,
                contactTitle, address, city, region,
                 postalCode,  country, phone, fax);

    CustomerDao customerDao = DaoFactory.GetDaoFactory().GetCustomerDao();
    return customerDao.UpdateCustomer(customer);
}

The Web Service classes in this project act as business objects or data clients. As you can see, the data client hasn't any understanding what is the data source. The DAO abstracts all manipulations to the data source.

Notes: Currently, in this code, the default DAO is the XML repository as it can work standalone. It will store the XML files locally in the App_Data folder (be sure that the ASPNET user has write permissions on your machine). If you are going to use it with MS SQL, you have to modify the web.config file. You need to comment the XMLDaoFactory code and uncomment the MSSqlDaoFactory code and also specify the connection string to your database as well to execute the SQL script that is in the SqlInstall folder. That is all what you need to migrate from one data source to another.

Links

Related articles:

Note

Please don't use this code as is in your projects. It's just a demo version that deals with data and needs to be tested well.

If you find this article interesting, please vote for me.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Belarus Belarus
Andrew Golik is a software professional working in Minsk, Belarus.
He enjoys design infrastructures based on object oriented paradigm. His programming experience includes ASP, ASP.NET, .NET, COM, JAVA, PHP, DHTML, AJAX, blah blah blah....

Andrew Golik's Blog

Comments and Discussions

 
GeneralI have some reservations about this topic Pin
Eugene Pechenezhsky11-Oct-07 14:31
Eugene Pechenezhsky11-Oct-07 14:31 
GeneralRe: I have some reservations about this topic [modified] Pin
Andrew Golik13-Oct-07 7:36
Andrew Golik13-Oct-07 7:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.