通过数据访问对象模式进行 Web 服务






3.89/5 (16投票s)
一个数据访问对象模式实现。
引言
访问数据源的方式取决于数据的来源。对持久化存储(如数据库)的访问,根据存储类型和供应商的实现方式,差异很大。ODBC API 允许应用程序使用 SQL 语句。然而,即使在 RDBMS 环境中,SQL 语句的实际语法和格式也会因特定的数据库产品而异。不同类型的持久化存储的差异更大。访问机制、支持的 API 和功能在不同类型的持久化存储(如 RDBMS、面向对象数据库、LDAP、平面文件、XML 文件等)之间存在差异。如此分散的数据源给应用程序带来了挑战,并可能在应用程序和数据源代码之间产生直接依赖。当业务组件需要访问数据源时,它们会使用适当的 API 来建立连接并操作数据源。但是,将数据访问代码包含在业务组件中会在业务组件和数据源实现之间引入紧密耦合。这种代码依赖使得从一种数据源迁移到另一种数据源变得困难。当数据源发生变化时,业务组件也必须随之更改以处理新的数据源类型。
解决方案
使用数据访问对象(DAO)来完成对数据源对象的所有操作。DAO 管理与数据源的连接以获取和存储数据。DAO 实现所有访问功能以与数据源协同工作。数据源是什么并不重要。它可以是任何持久化存储,如 RDBMS、LDAP 等存储库,甚至只是 XML 文件。依赖 DAO 的业务组件使用 DAO 向其客户端公开的简单接口。DAO 不会暴露数据源的实现,也没有必要这样做。因为当底层数据源发生变化时,DAO 接口不需要改变,这种能力使得 DAO 能够适应不同类型存储而无需在业务组件中处理。您也可以说 DAO 在组件和数据源对象之间充当适配器。
------------------ uses ------------------- encapsulates -----------
| BusinessObject | ------------> | DataAccessObject | --------------> | DataSource |
------------------ ------------------- ------------
\ /
\ /
\ /
obtains, modifies, and \ / save the transfer object into
creates the transfer object \ / persistent data storage
\ /
\ /
\ /
\/ \/
-----------------
| TransferObject |
-----------------
业务对象
该对象代表数据客户端。它是需要访问数据源以获取和修改数据的对象。
数据访问对象
该对象是此模式中的底层对象。它为客户端抽象了数据访问实现,以实现对数据源的透明访问。业务对象将数据创建和存储操作委托给数据访问对象。
数据源
该对象代表数据源的实现。它可以是任何持久化存储,例如 RDBMS、OODBMS、XML 存储库、平面文件系统等。
传输对象
该对象代表数据载体。数据访问对象使用此对象将数据返回给客户端,并接收更新和创建数据源中的数据。
示例项目
我提供了这个示例项目,其中包含两种 DAO:XmlRepository 和 MSSql。这个示例项目演示了使用此模式的便捷性。它还表明从一种数据源迁移到另一种数据源轻而易举。
如您所见,我使用了抽象工厂模式。DaoFactory
是所有 DAO 工厂的抽象类。
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;
}
}
}
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();
}
}
XmlDaoFactory
的实现相同,除了特定的更改。XmlDaoFactory
没有连接字符串,但它有指向 XML 文件的路径。
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();
}
}
此项目中只有两个业务对象:Customer
和 Order
。因此,我们需要有两个接口:CustomerDao
和 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);
}
这些接口描述了所有 DAO 实现的基本数据访问功能。一旦添加了新的接口方法,就必须修改该接口的所有 DAO 实现。
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
.......
}
}
XmlOrderDao
的实现是特定的,因为它使用 XML 文件来存储数据。
传输对象由 DAO 用于与数据客户端发送和接收数据。
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.....
从数据客户端使用 DAO 非常简单。
[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);
}
此项目中的 Web 服务类充当业务对象或数据客户端。如您所见,数据客户端不了解数据源是什么。DAO 抽象了对数据源的所有操作。
注意:目前,在此代码中,默认 DAO 是 XML 存储库,因为它可以在独立模式下运行。它将在 App_Data 文件夹中本地存储 XML 文件(请确保 ASPNET 用户在您的机器上具有写入权限)。如果您打算将其与 MS SQL 一起使用,则需要修改 web.config 文件。您需要注释掉 XMLDaoFactory 代码并取消注释 MSSqlDaoFactory 代码,并指定您的数据库的连接字符串,以执行 SqlInstall 文件夹中的 SQL 脚本。这就是您从一个数据源迁移到另一个数据源所需的一切。
链接
相关文章
- JavaScript 数据网格:https://codeproject.org.cn/KB/scripting/Javascript_DataGrid.aspx
- 此 Web 服务与使用 AJAX 技术的 JavaScript 数据网格联用的用法:https://codeproject.org.cn/KB/ajax/AJAX_DataGrid.aspx
注意
请勿直接在您的项目中使用此代码。它只是一个处理数据的演示版本,需要经过充分的测试。
如果您觉得这篇文章有趣,请为我投票。