概述
本篇就以前文的理论基础来实现一个简单查询功能的三层架构作为实例演示。方便起见,数据库就用Petshop的数据库。闲话不多述 了。架构内容如下:
实现过程
1 建立DBUtility类库项目,编写DBHelper.cs,代码如下
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Common;
using System.Data;
namespace DBUtility
{
public class DBHelper
{
private DbProviderFactory dbFactory;
private string connStr;
public DBHelper(string providerName,string connStr)
{
this.dbFactory = DbProviderFactories.GetFactory(providerName);
this.connStr = connStr;
}
/// <summary>
/// 执行sql查询
/// </summary>
/// <param name="sql"></param>
/// <returns></returns>
public DataSet Query(string sql)
{
using (DbConnection conn = dbFactory.CreateConnection())
{
conn.ConnectionString = connStr;
DataSet result = new DataSet();
DbCommand cmd = conn.CreateCommand();
if (conn.State != ConnectionState.Open)
conn.Open();
cmd.Connection = conn;
cmd.CommandText = sql;
cmd.CommandType = CommandType.Text;
DbDataAdapter adapter = dbFactory.CreateDataAdapter();
adapter.SelectCommand = cmd;
adapter.Fill(result);
cmd.Parameters.Clear();
return result;
}
}
}
}
作为演示代码,此处仅提供一个查询方法,读者可以自行添加所需的数据库操作方法,如增删改,带参数查询,执行存储过程,提供事务支持等。同样此处单独建立DBUtility项目来实现DBHelper,仅仅是方便演示代码,实际上DBHelper通过构造函数传入DbProviderFactory和数据库连接的信息,已成功的和整个项目解耦,可以编译为单独的DLL供数据访问层引用。但是下面显然还有两个难题需要解决,一是如何从用户界面层传递进来创建DbProviderFactory子类所需要的信息以及数据连接信息(综合来说就是访问一个数据库所需要的两个主要信息,一个是"什么库",另一个就是"怎么连",以下简称数据库实例信息),二是如何实现同时对多个数据库(种类也可能不同,如一个sql server,一个Oracle)的访问?与微软定义DbProviderFactory来创建一系列相关的ADO.NET对象的思路类似,我们也可以在三层架构中的数据访问层和业务逻辑层分别创建一个工厂类,负责创建本层的所有功能对象,而工厂类在实例化时接收数据库实例的信息,在创建功能对象时把下层的工厂实例传递进去。
2 数据访问层DataAccess项目的代码
using System;
using System.Collections.Generic;
using System.Text;
using DBUtility;
namespace DataAccess
{
public class DALFactory
{
private DBHelper dbHelper;
public DALFactory(string providerName,string connStr)
{
dbHelper = new DBUtility.DBHelper(providerName, connStr);
}
public ProductDAL CreateProductDAL()
{
return new ProductDAL(dbHelper);
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using DBUtility;
namespace DataAccess
{
public class ProductDAL
{
DBHelper helper;
public ProductDAL(DBHelper helper)
{
this.helper = helper;
}
public DataSet GetProducts()
{
string sql = ReadSQLFromXML("GetProduct");
return helper.Query(sql);
}
private string ReadSQLFromXML(string nodeName)
{
return "select * from SalesLT.Product";
}
}
}
3 业务逻辑层Business项目的代码
using System;
using System.Collections.Generic;
using System.Text;
using DataAccess;
namespace Business
{
public class BLLFactory
{
public DALFactory dalFactory;
public BLLFactory(string providerName, string connStr)
{
dalFactory = new DataAccess.DALFactory(providerName,connStr);
}
public ProductBLL CreateProductBLL()
{
return new ProductBLL(dalFactory);
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using DataAccess;
namespace Business
{
public class ProductBLL
{
DALFactory dalFactory;
public ProductBLL(DALFactory dalFactory)
{
this.dalFactory = dalFactory;
}
public DataSet GetProducts()
{
ProductDAL product = dalFactory.CreateProductDAL();
return product.GetProducts() ;
}
}
}
4 最后,创建一个控制台项目UI作为用户界面层,演示如何调用业务逻辑层功能对象。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
</configSections>
<connectionStrings>
<add name="UI.Settings1.Setting" connectionString="Data Source=localhost;Initial Catalog=temptdb;Integrated Security=True"
providerName="System.Data.SqlClient" />
<add name="UI.Settings2.Setting" connectionString="Data Source=sqlexpress;user = demo; password=demo"
providerName="System.Data.OracleClient" />
</connectionStrings>
</configuration>
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
namespace UI
{
public class GlobalObject
{
static ConnectionStringSettings settings1 = ConfigurationManager.ConnectionStrings["UI.Settings1.Setting"];
static ConnectionStringSettings settings2 = ConfigurationManager.ConnectionStrings["UI.Settings2.Setting"];
public static Business.BLLFactory bllFactory = new Business.BLLFactory(settings1.ProviderName, settings1.ConnectionString);
public static Business.BLLFactory bllFactory2 = new Business.BLLFactory(settings2.ProviderName, settings2.ConnectionString);
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
namespace UI
{
class Program
{
static void Main(string[] args)
{
Business.ProductBLL product = GlobalObject.bllFactory.CreateProductBLL();
DataSet ds = product.GetProducts();
Business.ProductBLL product2 = GlobalObject.bllFactory2.CreateProductBLL();
ds = product2.GetProducts();
}
}
}
总结:和微软官方的Petshop示例代码比较起来,在架构方面个人认为有以下几点改进:
1 把DBUtility抽象出来,无须对N种数据库实现N个IDAL接口,简化了架构。
2 可扩展性提高,当需要增加对某种数据库的支持时,只要其提供相应的集成于ADO.NET的抽象基类的provider即可,
通过修改配置文件便可实现对其的支持。
3 实现了在一个系统对多个数据库访问的支持。
注意:此文章属博主原创,转载请注明作者信息和原始链接,谢谢合作。
如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】按钮。
如果,您希望更容易地发现我的新博客,不妨点击一下左下角的【关注 lindping】。
因为,我的写作热情也离不开您的肯定支持。
感谢您的阅读,如果您对我的博客所讲述的内容有兴趣,请继续关注我的后续博客,我是lindping。