实现基于通用数据访问组件的三层架构之实战篇

概述

本篇就以前文的理论基础来实现一个简单查询功能的三层架构作为实例演示。方便起见,数据库就用Petshop的数据库。闲话不多述 了。架构内容如下:

  1. 构建通用数据访问组件DbHelper(只实现一个简单查询方法Query(string sql))
  2. 创建数据访问层,定义ProductDAL对象并实现一个方法GetProduct,读取xml文件的sql语句并调用Dbhelper的Query,返回product表的数据。
  3. 创建业务逻辑层,定义ProductBLL对象并实现GetPr oduct,方法(通过调用数据访问层GetProduct)。
  4. 创建用户界面层,调用业务逻辑层的GetProduct。

实现过程

    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项目的代码

  • 数据访问层工厂类,实例化时候接收数据库实例信息,以此创建DBHelper对象,并在创建功能对象时把 DBHelper传递进去,供功能对象调用。

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);

}

}

}

 

  • 数据访问层功能对象类,此处从sql文件读取sql语句的代码省略了,直接返回一个sql语句,实际中你应该明白怎么做的。

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作为用户界面层,演示如何调用业务逻辑层功能对象。

  • 在app.config建立两个数据库连接,一个sql server,一个 oracle(使用oralce的话数据访问层需要引入System.Data.OracleCient.dll)

<?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。

原文地址:https://www.cnblogs.com/lindping/p/2459604.html