![]() |
Web Development »
Web Services »
General
Intermediate
Web Service via Data Access Object PatternBy Andrew GolikData Access Object pattern implementation |
SQL, C# 2.0, Windows, .NET 2.0, ASP.NET, WebForms, SQL 2000, SQL 2005, VS2005, IE 6.0, IE 7, Architect, DBA, Dev
|
||||||||||
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
Access to the data source varies depending on source of data. Access to the persistent storage, such as to the database varies greatly depending on type of storage and vendor implementation. The ODBC API enables applications to use SQL statements. However, even within RDBMS environment the actual syntax and format of the SQL statement varies 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 database, LDAP, flat file, Xml file, and so forth). Such disparate data sources make challenges to applications and can potentially create a direct dependency between application and data source code. When business components need to access to the data source, they use appropriate APIs to create connectivity and manipulate the data source. But including the data access code within business components introduces tight coupling between the business components and data source implementation. Such code dependencies make it difficult to migrate form 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 manupulation to the data source object. The DAO manages the connection with datasource 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 a XML files. The business components that rely on DAO use simple interface exposed by DAO to its clients. The DAO doesn't show the certain 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 business component. You can also say that the DAO acts as adapter between components and data source object.
Picture 1. Relationships in 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 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 store actions to 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 client as well as to receive to update, create the data in the data source.I provided this sample of project with two kind of DAO: XmlRepository and MSSql. This sample of project demonstrates how to easy to use this pattern. It also shows that any migration from one datasource to another is a piece of cake.

As you can see I use the abstract factory model. The DaoFactory is abstract class for all dao factories.
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 certian implementation of the MSSqlDaoFactory.
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. The XmlDaoFactory hasn't the connection string, but it has paths to xml files.
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(); } } </orders></customers>
There are only two business objects in this project the Customer and Order. So we need to have two interface: the CustomerDao and OrderDao.
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); } </customer></order>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 certain implementation of OrderDao.
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 ....... } } </order>
The implementation of the XmlOrderDao is specific due to it uses xml files to store the data.
The transfer objects is used by DAO to send and receive data from data client.
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 data client.
[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 undestanding what is the data source. The Dao abstracts all manipulations to the data source.
Notes: Currently, in this code the default DAO is XML Repository as means that it can work standalone. It will store the xml files locally in the App_Data folder(be sure that ASPNET user has the write permissions on your machine). If you going to use it with MS SQL, you have to modify the web.config file. You need to comment the XMLDaoFactory and uncomment the MSSqlDaoFactory and also specify the connection string to your database as well as to execute the sql script that is in SqlInstall folder. That is all what you need to migrate from one datasource to another.
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 interested, please vote for me.
| You must Sign In to use this message board. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 9 Oct 2007 Editor: |
Copyright 2007 by Andrew Golik Everything else Copyright © CodeProject, 1999-2009 Web22 | Advertise on the Code Project |