• .net平台上实现数据库访问工厂,连接不同的数据库


    前言:最近由于项目需求变化,数据库将由sql server更换为mysql。涉及到大量的迁移工作,尤其dal层。于是产生了一个想法,实现一个数据库访问工厂,在更换数据库的时候,只需要在配置文件里更改一下配置即可。dal层代码不需要再做更改。

    珍重申明:整个思路参照了该网址下(http://www.xuebuyuan.com/2204740.html)的一片文章,对该文章的作者提出感谢!只是结合我们项目的特点,做了更改。

    实现步骤:整个数据库访问工厂DBFactory项目由5个文件组成。

    1:创建一个枚举,在DataProvider.cs文件里实现。

    public enum DataProvider
    {
    Oracle,
    SqlServer,
    MySql
    }

    主要应对主流的三大数据库。

    2:建立一个接口:IDBManager.cs。接口文件是实现工厂的必备,当然也可以用abstrct类代替。提供了一个数据库访问和操作的模板。

    public interface IDBManager
    {
    DataProvider ProviderType { get; set; }
    IDbConnection Connection { get; set; }
    IDataReader DataReader { get; set; }
    IDbCommand Command { get; set; }
    IDbTransaction Transaction { get; set; }
    IDbDataParameter[] Parameters { get; set; }
    string ConnectionString { get; set;}


    void Open();
    void Close();
    void Dispose();
    void CreateParameters(int paramsCount);
    void AddParameters(int index,string paramName,object objValue);
    void BeginTransaction();
    void CommitTransaction();
    void CloseReader();
    IDataReader ExecuteReader(CommandType commandType,string commandText);
    int ExecuteNonQuery(CommandType commandType,string commandText);
    object ExecuteScalar(CommandType commandType,string commandText);
    DataSet ExecuteDataSet(CommandType commandType,string commandText);
    DataTable ExecuteDataTable(CommandType commandType, string commandText);

    }

    3:建立一个工厂类,根据配置,返回相应的数据库操作过程中的对象(IDbConnection等)。DBManagerFactory.cs。

    public class DBManagerFactory
    {
    private DBManagerFactory() { }
    /// <summary>
    /// 根据配置中的数据库类型,返回相应的数据库连接
    /// </summary>
    /// <param name="providerType"></param>
    /// <returns></returns>
    public static IDbConnection GetConnection(DataProvider providerType)
    {
    IDbConnection iDbConnection;
    switch(providerType)
    {
    case DataProvider.SqlServer:
    iDbConnection = new SqlConnection();
    break;
    case DataProvider.MySql:
    iDbConnection = new MySqlConnection();
    break;
    case DataProvider.Oracle:
    iDbConnection = new OracleConnection();
    break;
    default:
    return null;
    }
    return iDbConnection;
    }


    public static IDbCommand GetCommand(DataProvider providerType)
    {
    IDbCommand iDbCommand;
    switch (providerType)
    {
    case DataProvider.SqlServer:
    iDbCommand = new SqlCommand();
    break;
    case DataProvider.MySql:
    iDbCommand = new MySqlCommand();
    break;
    case DataProvider.Oracle:
    iDbCommand = new OracleCommand();
    break;
    default:
    return null;
    }
    return iDbCommand;
    }

    /// <summary>
    /// 根据配置中的数据库类型,返回相应的数据适配器
    /// </summary>
    /// <param name="providerType"></param>
    /// <returns></returns>
    public static IDbDataAdapter GetDataAdapter(DataProvider providerType)
    {
    switch (providerType)
    {
    case DataProvider.SqlServer:
    return new SqlDataAdapter();
    case DataProvider.MySql:
    return new MySqlDataAdapter();
    case DataProvider.Oracle:
    return new OracleDataAdapter();
    default:
    return null;
    }
    }


    public static IDbTransaction GetTransaction(DataProvider providerType)
    {
    IDbConnection iDbConnection = GetConnection(providerType);
    IDbTransaction iDbTransaction =iDbConnection.BeginTransaction();

    return iDbTransaction;

    }

    /// <summary>
    /// 根据数据库类型和参数数量,创建相应的参数数组
    /// </summary>
    /// <param name="providerType"></param>
    /// <param name="paramsCount"></param>
    /// <returns></returns>
    public static IDbDataParameter[] GetParameters(DataProvider providerType, int paramsCount)
    {
    IDbDataParameter[] idbParams = new IDbDataParameter[paramsCount];

    switch (providerType)
    {
    case DataProvider.SqlServer:
    for (int i = 0; i < paramsCount; i++)
    {
    idbParams[i] = new SqlParameter();
    }
    break;
    case DataProvider.MySql:
    for (int i = 0; i < paramsCount; i++)
    {
    idbParams[i] = new MySqlParameter();
    }
    break;
    case DataProvider.Oracle:
    for(int i=0;i<paramsCount;i++)
    {
    idbParams[i] = new OracleParameter();
    }
    break;
    default:
    idbParams = null;
    break;
    }
    return idbParams;

    }

    4:创建DBManager.cs,实现了IDBManager接口。那么工厂DBManagerFactory就可以通过配置文件,实现DBManager的多态性,实例化以后可以操作不同的数据库了。

    public sealed class DBManager: IDBManager, IDisposable
    {
    #region 字段
    private DataProvider _providerType;

    private IDbConnection _idbConnection;

    private IDataReader _iDataReader;

    private IDbCommand _idbCommand;

    private IDbTransaction _idbTransaction;

    private IDbDataParameter[] _idbParameters;

    private string _connectionString;

    #endregion

    #region 属性

    public DataProvider ProviderType
    {
    get
    {
    return _providerType;
    }
    set
    {
    _providerType =value;
    }
    }


    public IDbConnection Connection
    {
    get
    {
    return _idbConnection;
    }
    set
    {
    _idbConnection = value;
    }
    }


    public IDataReader DataReader
    {
    get
    {
    return _iDataReader;
    }
    set
    {
    _iDataReader = value;
    }
    }

    public IDbCommand Command
    {
    get
    {
    return _idbCommand;
    }
    set
    {
    _idbCommand= value;
    }
    }


    public IDbTransaction Transaction
    {
    get
    {
    return _idbTransaction;
    }
    set
    {
    _idbTransaction = value;
    }
    }


    public IDbDataParameter[] Parameters
    {
    get
    {
    return _idbParameters;
    }
    set
    {
    _idbParameters = value;
    }
    }

    public string ConnectionString
    {
    get
    {
    return _connectionString;
    }
    set
    {
    _connectionString = value;
    }
    }
    #endregion

    #region 构造方法

    public DBManager()
    {
    }


    public DBManager(DataProvider providerType)
    {
    ProviderType=providerType;
    }


    public DBManager(DataProvider providerType,string connectionString)
    {
    ProviderType=providerType;
    ConnectionString=connectionString;
    }

    #endregion


    #region 公有方法

    public void Open()
    {
    Connection=DBManagerFactory.GetConnection(ProviderType);
    Connection.ConnectionString=ConnectionString;

    if(Connection.State!=ConnectionState.Open)
    {
    Connection.Open();
    }
    Command=DBManagerFactory.GetCommand(ProviderType);
    }


    public void Close()
    {
    if(Connection.State != ConnectionState.Closed)
    {
    Connection.Close();
    }
    }


    public void Dispose()
    {
    GC.SuppressFinalize(this);
    Close();
    Command=null;
    Transaction=null;
    Connection=null;
    }


    public void CreateParameters(int paramsCount)
    {
    Parameters=new IDbDataParameter[paramsCount];
    Parameters=DBManagerFactory.GetParameters(ProviderType, paramsCount);
    }

    public void AddParameters(int index,string paramName,object objValue)
    {
    if(index<Parameters.Length)
    {
    Parameters[index].ParameterName=paramName;
    Parameters[index].Value=objValue;
    }
    }

    public void BeginTransaction()
    {
    if(Transaction ==null)
    {
    Transaction=DBManagerFactory.GetTransaction(ProviderType);
    }
    Command.Transaction=Transaction;
    }


    public void CommitTransaction()
    {
    if(Transaction!= null)
    {
    Transaction.Commit();
    }
    Transaction=null;
    }


    public void CloseReader()
    {
    if(DataReader != null)
    {
    DataReader.Close();
    }
    }


    public IDataReader ExecuteReader(CommandType commandType,string commandText)
    {
    Command=DBManagerFactory.GetCommand(ProviderType);
    Command.Connection=Connection;
    PrepareCommand(Command, Connection, Transaction, commandType, commandText, Parameters);
    DataReader=Command.ExecuteReader();
    Command.Parameters.Clear();

    return DataReader;
    }


    public int ExecuteNonQuery(CommandType commandType,string commandText)
    {
    Command=DBManagerFactory.GetCommand(ProviderType);
    PrepareCommand(Command, Connection, Transaction, commandType, commandText, Parameters);

    int returnValue = Command.ExecuteNonQuery();
    Command.Parameters.Clear();

    return returnValue;
    }


    public object ExecuteScalar(CommandType commandType, string commandText)
    {
    Command=DBManagerFactory.GetCommand(ProviderType);
    PrepareCommand(Command, Connection, Transaction, commandType, commandText, Parameters);

    object returnValue = Command.ExecuteScalar();
    Command.Parameters.Clear();

    return returnValue;
    }


    public DataSet ExecuteDataSet(CommandType commandType, string commandText)
    {
    Command=DBManagerFactory.GetCommand(ProviderType);
    PrepareCommand(Command, Connection, Transaction, commandType, commandText, Parameters);
    IDbDataAdapter dataAdapter=DBManagerFactory.GetDataAdapter(ProviderType);
    dataAdapter.SelectCommand=Command;
    DataSet dataSet=new DataSet();
    dataAdapter.Fill(dataSet);
    Command.Parameters.Clear();

    return dataSet;
    }

    public DataTable ExecuteDataTable(CommandType commandType, string commandText)
    {
    Command = DBManagerFactory.GetCommand(ProviderType);
    PrepareCommand(Command, Connection, Transaction, commandType, commandText, Parameters);
    IDbDataAdapter dataAdapter = DBManagerFactory.GetDataAdapter(ProviderType);
    dataAdapter.SelectCommand = Command;
    DataSet dataSet = new DataSet();
    dataAdapter.Fill(dataSet);
    DataTable table = dataSet.Tables[0];
    Command.Parameters.Clear();

    return table;
    }
    #endregion

    #region 私有方法

    private void AttachParameters(IDbCommand command, IDbDataParameter[] commandParameters)
    {
    foreach(IDbDataParameter idbParameter in commandParameters)
    {
    if(idbParameter.Direction== ParameterDirection.InputOutput && idbParameter.Value== null)
    {
    idbParameter.Value=DBNull.Value;
    }

    command.Parameters.Add(idbParameter);
    }
    }


    private void PrepareCommand(IDbCommand command, IDbConnection connection, IDbTransaction transaction, CommandType commandType, string commandText, IDbDataParameter[] commandParameters)
    {
    command.Connection=connection;
    command.CommandText=commandText;
    command.CommandType=commandType;

    if(transaction != null)
    {
    command.Transaction=transaction;
    }

    if(commandParameters!= null)
    {
    AttachParameters(command, commandParameters);
    }
    }
    #endregion

    5:建立DBHelper类,封装了DBManager类,该类下面的建立了很多的static方法,供DAL层直接调用就可以了。

    /// <summary>
    /// 调用DBManager类,外部来直接调用DBHelper类即可
    /// </summary>
    public class DBHelper
    {
    private static readonly IDBManager dbManager=new DBManager(GetDataProvider(), GetConnectionString());


    //从配置文件中选择数据库类型
    private static DataProvider GetDataProvider()
    {
    string providerType = ConfigurationManager.AppSettings["DataProvider"];
    DataProvider dataProvider;

    switch(providerType)
    {
    case "Oracle":
    dataProvider=DataProvider.Oracle;
    break;

    case "SqlServer":
    dataProvider=DataProvider.SqlServer;
    break;

    case "MySql":
    dataProvider=DataProvider.MySql;
    break;
    default:
    return DataProvider.SqlServer;
    }

    return dataProvider;
    }

    //从配置文件获取连接字符串
    private static string GetConnectionString()
    {
    return ConfigurationManager.ConnectionStrings["ConnString"].ConnectionString;
    }

    /// <summary>
    /// 关闭数据库连接的方法
    /// </summary>
    public static void Close()
    {
    dbManager.Dispose();
    }
    /// <summary>
    /// 创建参数
    /// </summary>
    /// <param name="paramsCount"></param>
    public static void CreateParameters(int paramsCount)
    {
    dbManager.CreateParameters(paramsCount);
    }

    /// <summary>
    /// 添加参数
    /// </summary>
    /// <param name="index"></param>
    /// <param name="paramName"></param>
    /// <param name="objValue"></param>
    public static void AddParameters(int index,string paramName,object objValue)
    {
    dbManager.AddParameters(index, MatchParameters(paramName), objValue);
    }

    /// <summary>
    /// 拼接sql语句执行非查询操作
    /// </summary>
    /// <param name="sqlString"></param>
    /// <returns></returns>
    public static bool ExecuteNonQueryByText(string sqlString)
    {
    try
    {
    dbManager.Open();

    return dbManager.ExecuteNonQuery(CommandType.Text, sqlString) > 0 ? true :false;
    }
    catch(Exception e)
    {
    throw new Exception(e.Message);
    }

    finally
    {
    dbManager.Dispose();
    }
    }
    /// <summary>
    /// 调用存储过程执行非查询操作
    /// </summary>
    /// <param name="sqlString"></param>
    /// <returns></returns>
    public static bool ExecuteNonQueryByProcedure(string sqlString)
    {
    try
    {
    dbManager.Open();

    return dbManager.ExecuteNonQuery(CommandType.StoredProcedure, sqlString) > 0 ? true : false;
    }
    catch (Exception e)
    {
    throw new Exception(e.Message);
    }

    finally
    {
    dbManager.Dispose();
    }
    }

    /// <summary>
    /// 拼接sql语句执行查询操作,返回datareader
    /// </summary>
    /// <param name="sqlString"></param>
    /// <returns></returns>
    public static IDataReader ExecuteReaderByText(string sqlString)
    {
    try
    {
    dbManager.Open();
    return dbManager.ExecuteReader(CommandType.Text, sqlString);
    }
    catch(Exception e)
    {
    throw new Exception(e.Message);
    }

    }
    /// <summary>
    /// 调用存储过程执行查询操作,返回datareader
    /// </summary>
    /// <param name="sqlString"></param>
    /// <returns></returns>
    public static IDataReader ExecuteReaderByProcedure(string sqlString)
    {
    try
    {
    dbManager.Open();
    return dbManager.ExecuteReader(CommandType.StoredProcedure, sqlString);
    }
    catch (Exception e)
    {
    throw new Exception(e.Message);
    }


    }

    /// <summary>
    /// 拼接sql语句执行查询操作,返回dataset
    /// </summary>
    /// <param name="sqlString"></param>
    /// <returns></returns>
    public static DataSet ExecuteDataSetByText(string sqlString)
    {
    try
    {
    dbManager.Open();
    return dbManager.ExecuteDataSet(CommandType.Text, sqlString);
    }
    catch (Exception e)
    {
    throw new Exception(e.Message);
    }
    finally
    {
    dbManager.Dispose();
    }
    }
    /// <summary>
    /// 调用存储过程执行查询操作,返回dataset
    /// </summary>
    /// <param name="sqlString"></param>
    /// <returns></returns>
    public static DataSet ExecuteDataSetByProcedure(string sqlString)
    {
    try
    {
    dbManager.Open();
    return dbManager.ExecuteDataSet(CommandType.StoredProcedure, sqlString);
    }
    catch (Exception e)
    {
    throw new Exception(e.Message);
    }
    finally
    {
    dbManager.Dispose();
    }

    }

    /// <summary>
    /// 拼接sql语句执行查询操作,返回datatable
    /// </summary>
    /// <param name="sqlString"></param>
    /// <returns></returns>
    public static DataTable ExecuteDataTableByText(string sqlString)
    {
    try
    {
    dbManager.Open();
    return dbManager.ExecuteDataTable(CommandType.Text, sqlString);
    }
    catch (Exception e)
    {
    throw new Exception(e.Message);
    }
    finally
    {
    dbManager.Dispose();
    }
    }
    /// <summary>
    /// 调用存储过程执行查询操作,返回datatable
    /// </summary>
    /// <param name="sqlString"></param>
    /// <returns></returns>
    public static DataTable ExecuteDataTableByProcedure(string sqlString)
    {
    try
    {
    dbManager.Open();
    return dbManager.ExecuteDataTable(CommandType.StoredProcedure, sqlString);
    }
    catch (Exception e)
    {
    throw new Exception(e.Message);
    }
    finally
    {
    dbManager.Dispose();
    }
    }

    /// <summary>
    /// 拼接sql语句执行查询操作,返回首条
    /// </summary>
    /// <param name="sqlString"></param>
    /// <returns></returns>
    public static object ExecuteScalarByText(string sqlString)
    {
    try
    {
    dbManager.Open();
    return dbManager.ExecuteScalar(CommandType.Text,sqlString);
    }
    catch (Exception e)
    {
    throw new Exception(e.Message);
    }
    finally
    {
    dbManager.Dispose();
    }
    }

    /// <summary>
    /// 调用存储过程执行查询操作,返回首条
    /// </summary>
    /// <param name="sqlString"></param>
    /// <returns></returns>
    public static object ExecuteScalarByProcedure(string sqlString)
    {
    try
    {
    dbManager.Open();
    return dbManager.ExecuteScalar(CommandType.StoredProcedure, sqlString);
    }
    catch (Exception e)
    {
    throw new Exception(e.Message);
    }
    finally
    {
    dbManager.Dispose();
    }
    }


    #region 私有方法
    /// <summary>
    /// 由于各个数据库的参数格式不同,此处为了保证dal层不因换数据库而修改
    /// </summary>
    /// <param name="paramName">参数类型</param>
    /// <returns></returns>
    private static string MatchParameters(string paramName)
    {
    string providerType = ConfigurationManager.AppSettings["DataProvider"];

    string result=String.Empty;
    switch (providerType)
    {
    case "Oracle":
    result = paramName.StartsWith("@") ? paramName.Substring(1) : paramName;
    break;

    case "SqlServer":
    result = paramName.StartsWith("@") ? paramName : paramName.Insert(0,"@");
    break;
    case "MySql":
    result = paramName.StartsWith("@") ? paramName.Substring(1) : paramName;
    break;
    default:
    return null;
    }
    return result;
    }

    #endregion

    注意事项:1)在DAL层提供参数和存储过程名字来调用存储过程,由于sql server存储过程参数钱必须有@,而其他没有。为了在更换数据库的时候,完全不对dal更改代码。所以在DBHelper类中加了一个方法:

    #region 私有方法
    /// <summary>
    /// 由于各个数据库的参数格式不同,此处为了保证dal层不因换数据库而修改
    /// </summary>
    /// <param name="paramName">参数类型</param>
    /// <returns></returns>
    private static string MatchParameters(string paramName)
    {
    string providerType = ConfigurationManager.AppSettings["DataProvider"];

    string result=String.Empty;
    switch (providerType)
    {
    case "Oracle":
    result = paramName.StartsWith("@") ? paramName.Substring(1) : paramName;
    break;

    case "SqlServer":
    result = paramName.StartsWith("@") ? paramName : paramName.Insert(0,"@");
    break;
    case "MySql":
    result = paramName.StartsWith("@") ? paramName.Substring(1) : paramName;
    break;
    default:
    return null;
    }
    return result;
    }

    #endregion

    有了这个方法,我们在写dal层的时候,可以统一将存储过程参数加@,或是不加。

    2)在工厂类中,需要引用

    using System.Data;
    using System.Data.SqlClient;
    using MySql.Data.MySqlClient;
    using Devart.Data.Oracle;

    当然前提是该项目下,引用几个dll。

    几个类库。其中MySql.Data.MySqlClient这个需要去mysql官网上下载驱动。而对于oracle我选择了免费版的devart提供的驱动。

  • 相关阅读:
    GraphQL:Descriptor Attributes
    C++ 条件变量
    C++ future
    C++ 互斥
    C++ 通用锁管理
    并发
    C++ 线程
    智能指针
    PMP4.项目整合管理4.7结束项目或阶段
    PMP4.项目整合管理4.5监控项目工作
  • 原文地址:https://www.cnblogs.com/neughj/p/4895050.html
Copyright © 2020-2023  润新知