概述

需求

有时我们的系统需要支持多种数据库,如即要支持MSSQL server又要同时支持Oracle database.而如果我们为些实现两套数据库操作的方式,就会不能很好的达到软件设计的目标:高内聚,低偶合。

设计

采取策略模式(Strategy),它定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法的变化不会影响到使用算法的客户。

优点:

1、 简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。
2、 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
3、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。

缺点:
1、 因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。
2、 在基本的策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象。(这本身没有解除客户端需要选择判断的压力,而策略模式与简单工厂模式结合后,选择具体实现的职责也可以由Context来承担,这就最大化的减轻了客户端的压力。)

DBHelp设计目标,同时支持Sqlite、Oracle 、MySql 、MsSql,类UML图设计如下:

有了上面的设计图如后,我们先创建Enums:

/********************************************************************************
** Class Name:   Enums
** Author:      Spring Yang
** Create date: 2013-3-16
** Modify:      Spring Yang
** Modify Date: 2013-3-16
** Summary:     Enums  class
*********************************************************************************/namespace BlogDBHelp
{using System;[Serializable]public enum SqlSourceType{Oracle,MSSql,MySql,SQLite}
}

再创建IDBHelp接口:

/********************************************************************************
** Class Name:   IDBHelp
** Author:      Spring Yang
** Create date: 2013-3-16
** Modify:      Spring Yang
** Modify Date: 2013-3-16
** Summary:     IDBHelp interface
*********************************************************************************/namespace BlogDBHelp
{using System.Collections.Generic;using System.Data;using System.Data.Common;public interface IDBHelp{/// <summary>/// Gets the connection string/// </summary>string ConnectionString { get; set; }/// <summary>/// Gets or sets the max connection count/// </summary>int MaxConnectionCount { get; set; }/// <summary>/// Gets or sets the sql source type/// </summary>SqlSourceType DataSqlSourceType { get; }/// <summary>/// Execute query by stored procedure /// </summary>/// <param name="cmdText">stored procedure</param>/// <returns>DataSet</returns>DataSet ExecuteQuery(string cmdText);/// <summary>/// Execute non query by stored procedure and parameter list/// </summary>/// <param name="cmdText">stored procedure</param>/// <returns>execute count</returns>int ExecuteNonQuery(string cmdText);/// <summary>/// Execute scalar by store procedure/// </summary>/// <param name="cmdText">store procedure</param>/// <returns>return value</returns>object ExecuteScalar(string cmdText);/// <summary>/// Get data base parameter by parameter name and parameter value/// </summary>/// <param name="key">parameter name</param>/// <param name="value">parameter value</param>/// <returns>sql parameter</returns>DbParameter GetDbParameter(string key, object value);/// <summary>/// Get data base parameter by parameter name and parameter value/// and parameter direction /// </summary>/// <param name="key">parameter name</param>/// <param name="value">parameter value</param>/// <param name="direction">parameter direction </param>/// <returns>data base parameter</returns>DbParameter GetDbParameter(string key, object value, ParameterDirection direction);/// <summary>/// Read entity list by  store procedure/// </summary>/// <typeparam name="T">entity</typeparam>/// <param name="cmdText">store procedure</param>/// <returns>entity list</returns>List<T> ReadEntityList<T>(string cmdText) where T : new();/// <summary>/// Get dictionary result by store procedure and parameters and string list/// </summary>/// <param name="cmdText">store procedure</param>/// <param name="stringlist">string list</param>/// <returns>result list</returns>List<Dictionary<string, object>> GetDictionaryList(string cmdText,List<string> stringlist);/// <summary>/// Batch execute ExecuteNonQuery by cmdText list/// </summary>/// <param name="cmdList">cmd text list</param>/// <returns>execute true or not</returns>bool BatchExecuteNonQuery(List<string> cmdList);}
}

再创建AbstractDBHelp 抽象类:

/********************************************************************************
** Class Name:   AbstractDBHelp
** Author:      Spring Yang
** Create date: 2013-3-16
** Modify:      Spring Yang
** Modify Date: 2013-3-16
** Summary:     AbstractDBHelp interface
*********************************************************************************/namespace BlogDBHelp
{using System;using System.Collections.Generic;using System.Configuration;using System.Data;using System.Data.Common;using System.Reflection;using System.Threading;public abstract class AbstractDBHelp : IDBHelp{#region Private Propertyprivate static int _currentCount;private int _maxConnectionCount;private string _connectionString;#endregion#region Private Methodsprivate void AddConnection(){if (_currentCount < MaxConnectionCount)_currentCount++;else{while (true){Thread.Sleep(5);if (_currentCount < MaxConnectionCount){_currentCount++;break;}}}}private void RemoveConnection(){_currentCount--;}/// <summary>/// Execute query by stored procedure and parameter list/// </summary>/// <param name="cmdText">stored procedure and parameter list</param>/// <param name="parameters">parameter list</param>/// <returns>DataSet</returns>private DataSet ExecuteQuery(string cmdText, List<DbParameter> parameters){using (var conn = GetConnection(ConnectionString)){conn.Open();using (var command = conn.CreateCommand()){var ds = new DataSet();PrepareCommand(command, conn, cmdText, parameters);var da = GetDataAdapter(command);da.Fill(ds);return ds;}}}/// <summary>/// Execute non query by stored procedure and parameter list/// </summary>/// <param name="cmdText">stored procedure</param>/// <param name="parameters">parameter list</param>/// <returns>execute count</returns>private int ExecuteNonQuery(string cmdText, List<DbParameter> parameters){using (var conn = GetConnection(ConnectionString)){conn.Open();using (var command = conn.CreateCommand()){PrepareCommand(command, conn, cmdText, parameters);return command.ExecuteNonQuery();}}}public bool BatchExecuteNonQuery(List<string> cmdList){using (var conn = GetConnection(ConnectionString)){conn.Open();using (var transaction = conn.BeginTransaction()){foreach (var cmdText in cmdList){if (string.IsNullOrEmpty(cmdText)) continue;using (var command = conn.CreateCommand()){try{command.CommandText = cmdText;command.Transaction = transaction;command.ExecuteNonQuery();}finally{command.CommandText = null;command.Dispose();}}}try{transaction.Commit();return true;}catch{transaction.Rollback();return false;}finally{transaction.Dispose();conn.Dispose();conn.Close();cmdList.Clear();}}}}/// <summary>/// Execute reader by store procedure and parameter list/// </summary>/// <param name="cmdText">store procedure</param>/// <param name="parameters">parameter list</param>/// <param name="conn">database connection </param>/// <returns>data reader</returns>public DbDataReader ExecuteReader(string cmdText, List<DbParameter> parameters, out DbConnection conn){conn = GetConnection(ConnectionString);conn.Open();AddConnection();var command = conn.CreateCommand();PrepareCommand(command, conn, cmdText, parameters);var dataReader = command.ExecuteReader();RemoveConnection();return dataReader;}/// <summary>/// Execute reader by store procedure and parameter list/// </summary>/// <param name="cmdText">store procedure</param>/// <param name="parameters">parameter list</param>/// <returns>data reader</returns> private List<T> ReadEntityList<T>(string cmdText, List<DbParameter> parameters) where T : new(){using (var conn = GetConnection(ConnectionString)){conn.Open();using (var command = conn.CreateCommand()){PrepareCommand(command, conn, cmdText, parameters);var dataReader = command.ExecuteReader();return ReadEntityListByReader<T>(dataReader);}}}/// <summary>/// Read entity list by reader/// </summary>/// <typeparam name="T">entity</typeparam>/// <param name="reader">data reader</param>/// <returns>entity</returns>private List<T> ReadEntityListByReader<T>(DbDataReader reader) where T : new(){var listT = new List<T>();using (reader){while (reader.Read()){var fileNames = new List<string>();for (int i = 0; i < reader.VisibleFieldCount; i++){fileNames.Add(reader.GetName(i));}var inst = new T();foreach (var pi in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public)){if (!fileNames.Exists(fileName => string.Compare(fileName, pi.Name, StringComparison.OrdinalIgnoreCase) == 0))continue;object obj;try{obj = reader[pi.Name];}catch (Exception){continue;}if (obj == DBNull.Value || obj == null)continue;var si = pi.GetSetMethod();if (si == null)continue;if (pi.PropertyType == typeof(bool?))pi.SetValue(inst, Convert.ToBoolean(obj), null);else if (pi.PropertyType == typeof(string))pi.SetValue(inst, obj.ToString(), null);else if (pi.PropertyType == typeof(Int32))pi.SetValue(inst, Convert.ToInt32(obj), null);else if (pi.PropertyType == typeof(Int64))pi.SetValue(inst, Convert.ToInt64(obj), null);else if (pi.PropertyType == typeof(decimal))pi.SetValue(inst, Convert.ToDecimal(obj), null);elsepi.SetValue(inst, obj, null);}listT.Add(inst);}}return listT;}/// <summary>/// Get Dictionary list by string list/// </summary>/// <param name="cmdText">Store procedure</param>/// <param name="parameters">parameter list</param>/// <param name="stringlist">string list</param>/// <returns>result list</returns>private List<Dictionary<string, object>> GetDictionaryList(string cmdText, List<DbParameter> parameters, List<string> stringlist){using (var conn = GetConnection(ConnectionString)){AddConnection();using (var command = conn.CreateCommand()){PrepareCommand(command, conn, cmdText, parameters);var dataReader = command.ExecuteReader();RemoveConnection();return ReadStringListByReader(dataReader, stringlist);}}}/// <summary>/// Read dictionary list by reader and string list/// </summary>/// <param name="reader">Db data reader</param>/// <param name="stringlist">string</param>/// <returns>result list</returns>private List<Dictionary<string, object>> ReadStringListByReader(DbDataReader reader, List<string> stringlist){var listResult = new List<Dictionary<string, object>>();using (reader){while (reader.Read()){var dicResult = new Dictionary<string, object>();foreach (var key in stringlist){if (!stringlist.Exists(fileName => string.Compare(fileName, key, StringComparison.OrdinalIgnoreCase) == 0))continue;object obj;try{obj = reader[key];}catch (Exception){continue;}if (obj == DBNull.Value || obj == null)continue;dicResult.Add(key, obj);}listResult.Add(dicResult);}}return listResult;}/// <summary>/// Execute scalar by store procedure and parameter list/// </summary>/// <param name="cmdText">store procedure</param>/// <param name="parameters">parameter list</param>/// <returns>return value</returns>private object ExecuteScalar(string cmdText, List<DbParameter> parameters){using (var conn = GetConnection(ConnectionString)){conn.Open();using (var command = conn.CreateCommand()){PrepareCommand(command, conn, cmdText, parameters);return command.ExecuteScalar();}}}/// <summary>/// Prepare the execute command/// </summary>/// <param name="cmd">my sql command</param>/// <param name="conn">my sql connection</param>/// <param name="cmdText">stored procedure</param>/// <param name="parameters">parameter list</param>private void PrepareCommand(DbCommand cmd, DbConnection conn, string cmdText, List<DbParameter> parameters){if (conn.State != ConnectionState.Open)conn.Open();cmd.Parameters.Clear();cmd.Connection = conn;cmd.CommandText = cmdText;cmd.CommandType = CommandType.Text;cmd.CommandTimeout = 30;if (parameters != null)foreach (var parameter in parameters){cmd.Parameters.Add(parameter);}}#endregion#region Public Propertypublic int MaxConnectionCount{get{if (_maxConnectionCount <= 0)_maxConnectionCount = 100;return _maxConnectionCount;}set { _maxConnectionCount = value; }}public abstract SqlSourceType DataSqlSourceType { get; }#endregion#region Protected Methodprotected abstract DbDataAdapter GetDataAdapter(DbCommand command);protected abstract DbConnection GetConnection(string connectionString);#endregion#region Public Methods/// <summary>/// Gets the connection string/// </summary>public string ConnectionString{get{if (_connectionString == null)_connectionString = ConfigurationManager.ConnectionStrings[""].ConnectionString;return _connectionString;}set { _connectionString = value; }}/// <summary>/// Execute query by stored procedure and parameter list/// </summary>/// <param name="cmdText">stored procedure and parameter list</param>/// <returns>DataSet</returns>public DataSet ExecuteQuery(string cmdText){try{AddConnection();return ExecuteQuery(cmdText, new List<DbParameter>());}finally{RemoveConnection();}}/// <summary>/// Execute non query by stored procedure and parameter list/// </summary>/// <param name="cmdText">stored procedure</param>/// <returns>execute count</returns>public int ExecuteNonQuery(string cmdText){try{AddConnection();return ExecuteNonQuery(cmdText, new List<DbParameter>());}finally{RemoveConnection();}}/// <summary>/// Execute scalar by store procedure and parameter list/// </summary>/// <param name="cmdText">store procedure</param>/// <returns>return value</returns>public object ExecuteScalar(string cmdText){try{AddConnection();return ExecuteScalar(cmdText, new List<DbParameter>());}finally{RemoveConnection();}}/// <summary>/// Get data base parameter by parameter name and parameter value/// </summary>/// <param name="key">parameter name</param>/// <param name="value">parameter value</param>/// <returns>my sql parameter</returns>public abstract DbParameter GetDbParameter(string key, object value);/// <summary>/// Get data base parameter by parameter name and parameter value/// and parameter direction /// </summary>/// <param name="key">parameter name</param>/// <param name="value">parameter value</param>/// <param name="direction">parameter direction </param>/// <returns>data base parameter</returns>public DbParameter GetDbParameter(string key, object value, ParameterDirection direction){var parameter = GetDbParameter(key, value);parameter.Direction = direction;return parameter;}/// <summary>/// Get Dictionary list by string list/// </summary>/// <param name="cmdText">Store procedure</param>/// <param name="stringlist">string list</param>/// <returns>result list</returns>public List<Dictionary<string, object>> GetDictionaryList(string cmdText, List<string> stringlist){return GetDictionaryList(cmdText, new List<DbParameter>(), stringlist);}/// <summary>/// Execute reader by store procedure/// </summary>/// <param name="cmdText">store procedure</param>/// <returns>data reader</returns> public List<T> ReadEntityList<T>(string cmdText) where T : new(){try{AddConnection();return ReadEntityList<T>(cmdText, new List<DbParameter>());}finally{RemoveConnection();}}#endregion}
}

再创建MSSqlHelp 类:

/********************************************************************************
** Class Name:   MySqlHelp
** Author:      Spring Yang
** Create date: 2013-3-16
** Modify:      Spring Yang
** Modify Date: 2013-3-16
** Summary:     MySqlHelp class
*********************************************************************************/namespace BlogDBHelp
{using System.Data.Common;using System.Data.SqlClient;public class MSSqlHelp : AbstractDBHelp{#region Protected Methodprotected override DbDataAdapter GetDataAdapter(DbCommand command){return new SqlDataAdapter(command as SqlCommand);}protected override DbConnection GetConnection(string connectionString){return new SqlConnection(connectionString);}#endregion#region Public Mehtodpublic override SqlSourceType DataSqlSourceType{get { return SqlSourceType.MSSql; }}public override DbParameter GetDbParameter(string key, object value){return new SqlParameter(key, value);}#endregion}
}

再创建MySqlHelp类

/********************************************************************************
** Class Name:   MySqlHelp
** Author:      Spring Yang
** Create date: 2013-3-16
** Modify:      Spring Yang
** Modify Date: 2013-3-16
** Summary:     MySqlHelp class
*********************************************************************************/namespace BlogDBHelp
{using System.Data.Common;using MySql.Data.MySqlClient;public class MySqlHelp : AbstractDBHelp{#region Protected Methodprotected override DbDataAdapter GetDataAdapter(DbCommand command){return new MySqlDataAdapter();}protected override DbConnection GetConnection(string connectionString){return new MySqlConnection(connectionString);}#endregion#region Public Mehtodpublic override DbParameter GetDbParameter(string key, object value){return new MySqlParameter(key, value);}public override SqlSourceType DataSqlSourceType{get { return SqlSourceType.MySql; }}#endregion}
}

再创建OracleHelp类:

/********************************************************************************
** Class Name:   OracleHelp
** Author:      Spring Yang
** Create date: 2013-3-16
** Modify:      Spring Yang
** Modify Date: 2013-3-16
** Summary:     OracleHelp class
*********************************************************************************/namespace BlogDBHelp
{using System.Data.Common;using Oracle.DataAccess.Client;public class OracleHelp : AbstractDBHelp{#region Protected Methodprotected override DbDataAdapter GetDataAdapter(DbCommand command){return new OracleDataAdapter(command as OracleCommand);}protected override DbConnection GetConnection(string connectionString){return new OracleConnection(connectionString);}#endregion#region Public Mehtodpublic override DbParameter GetDbParameter(string key, object value){return new OracleParameter(key, value);}public override SqlSourceType DataSqlSourceType{get { return SqlSourceType.Oracle; }}#endregion}
}

再创建SQLiteHelp类:

/********************************************************************************
** Class Name:   SQLiteHelp
** Author:      Spring Yang
** Create date: 2013-3-16
** Modify:      Spring Yang
** Modify Date: 2013-3-16
** Summary:     SQLiteHelp class
*********************************************************************************/namespace BlogDBHelp
{using System.Data.Common;using System.Data.SQLite;public class SQLiteHelp : AbstractDBHelp{#region Protected Methodprotected override DbDataAdapter GetDataAdapter(DbCommand command){return new SQLiteDataAdapter(command as SQLiteCommand);}protected override DbConnection GetConnection(string connectionString){return new SQLiteConnection(connectionString);}#endregion#region Public Mehtodpublic override DbParameter GetDbParameter(string key, object value){return new SQLiteParameter(key, value);}public override SqlSourceType DataSqlSourceType{get { return SqlSourceType.SQLite; }}#endregion}
}

仔细观察上面代码,发现每增加一种数据库的支持,我们只需实现几个特有抽象方法就可以了,而调用只需像如下就可以了。

IDBHelp  _dbHelpInstance = new SQLiteHelp{ConnectionString ="";    };

欢迎各位参与讨论,如果觉得对你有帮助,请点击    推荐下,万分谢谢.

作者:spring yang

出处:http://www.cnblogs.com/springyangwc/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载于:https://www.cnblogs.com/springyangwc/archive/2013/03/17/2964428.html

策略模式实现支持多种类数据库的DBHelp相关推荐

  1. mysql 数据库dbhelp_策略模式实现支持多种类数据库的DBHelp

    概述 需求 有时我们的系统需要支持多种数据库,如即要支持MSSQL server又要同时支持Oracle database.而如果我们为些实现两套数据库操作的方式,就会不能很好的达到软件设计的目标:高 ...

  2. 【JDK8语法新特性】:超全总结{lamda,stream,optional,新日期类API},JDK8对策略模式支持,可以直接贴代码运行测试。

    文章目录 Java8新特性 速度快 代码更少(增加了新的语法,lamda表达式)(主要) 强大的Stream API(主要) 便于并行 最大减少空指针异常(Optional API) 提供了线程安全的 ...

  3. 行云管家 V4.7产品新特性-国际化版本、支持Oracle的数据库审计、主机密码自动修改策略 发布日期:2018-11-22...

    行云管家在线体验: 行云管家[官网]-领先的云计算管理平台-云安全,堡垒机,自动化运维​ 行云管家新手有礼活动: 行云管家新手有礼,新用户1元即可体验专业版-优惠券​ 发布日期:2018-11-22 ...

  4. 部署支持使用Redis哨兵模式,支持纳管ClickHouse数据库,JumpServer堡垒机v2.28.0发布

    2022年11月21日,JumpServer开源堡垒机正式发布v2.28.0版本.在这一版本中,JumpServer的部署支持使用Redis哨兵集群作为后端缓存数据库,从而使系统更加健壮和高可用.操作 ...

  5. fabric.js 不同类型 不同控件_策略模式支持不同类型的消息队列

    需求来源 现有采集数据平台:主要是通过snmp协议等各种协议从不同的系统中获取数据,并将数据发送到kafka中. 最近在和项目经理聊天的过程中发现现有一个客户数据量不大,数万级别,这样的客户还不少,使 ...

  6. 图解Java设计模式学习笔记——行为型模式(模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式)

    一.模板方法模式(模板模式)--钩子方法 1.需求-豆浆制作问题 编写制作豆浆的程序,说明如下: 制作豆浆的流程选材-->添加配料-->浸泡-->放到豆浆机打碎. 通过添加不同的配料 ...

  7. 设计模式之策略模式(Strategy)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  8. else 策略模式去掉if_设计模式(三)——简单的状态模式代替if-else

    博主将会针对Java面试题写一组文章,包括J2ee,SQL,主流Web框架,中间件等面试过程中面试官经常问的问题,欢迎大家关注.一起学习,一起成长. 前言 大多数开发人员现在还在使用if else的过 ...

  9. 运用单例模式、建造者模式和策略模式实现异步加载Android联系人资料

    学完设计模式很久了,最近又在看Android联系人提供程序的官方文档,于是就想实现一个方便的联系人管理程序demo,而联系人管理程序demo的核心就是要实现一个异步加载联系人资料的类,于是就有了下文. ...

最新文章

  1. 观点 | 医疗AI:新瓶装旧酒VS新瓶装新酒?——道彤投资创始合伙人孙琦
  2. 【剑指offer-Java版】37两个链表的第一个公共结点
  3. 谷歌大罢工组织者离职:自曝不得不走,“遭遇秋后算账”
  4. python 报错 most likely due to a circular import 解决方法
  5. python循环中append_[Python]list.append()在for循环中每次添加的都是最后的一个元素
  6. keyStore vs trustStore--转载
  7. oracle基础琐碎总结-----Where和Having的区别与联系
  8. jQuery的this $this $(this)
  9. 公共课计算机基础怎么样,公共课第一学期《计算机基础》
  10. 小强系列之大话移动测试
  11. python学习实例(4)
  12. 《JavaScript高级程序设计(第四版)》红宝书学习笔记(1)
  13. 景观分析工具:arcgis中patch analysis模块
  14. JavaScript-DOM(2)
  15. iview使用之怎样通过render函数在table组件表头添加图标及判断多个状态
  16. Xposed拦截抽象方法
  17. Linux内核多线程(四)
  18. 给树莓派安装手柄驱动
  19. 西电网络攻防大赛--渗透测试第五题
  20. 大企崛起的唯一“真相”!

热门文章

  1. rsync + inotify数据同步
  2. 简单脚本之显示系统当前的一些信息
  3. Oracle中单双引号
  4. 关押罪犯 扩展域并查集
  5. AngularJS第六课(路由)
  6. docker镜像-运行
  7. Python教程-python字典中key的灵活使用fromkeys()
  8. SharePoint 2013 版本功能对比
  9. 简单几行javascript代码,实现动态倒计时功能
  10. 超级*** 08鬼斧神工