本方案可实现仅修改app.config即可连接不同数据库,但是设计数据库时需要注意各种数据库的数据类型是不一样的。

各种不同数据库的Connection、Command、DataAdapter、Transaction和Parameter都继承自IDbConnection、IDbCommand、IDbDataAdapter、IDbTransaction和IDbDataParameter,用一个工厂来实现接口的实例即可实现连接不同数据库。

首先,需要新建一个类库,命名为DbManager,此类库需要5个文件, 

1、创建一个枚举类型:DataProvider.cs

namespace DbManager


    public enum DataProvider
    {
        Oracle,
        SqlServer,
        OleDb,
        Odbc,
        MySql
    }
}

2、创建一个工厂类,用来产生以上不同数据库的实例:DBManagerFactory.cs

using System.Data;
using System.Data.Odbc;
using System.Data.SqlClient;
using System.Data.OleDb;
using System.Data.OracleClient; //需要添加引用
using MySql.Data.MySqlClient;   //请自行安装MySQLConnector/Net后添加引用

namespace DbManager
{
    
public sealed class DBManagerFactory
    {
        
private DBManagerFactory()
        {
        }

        
public static IDbConnection GetConnection(DataProvider providerType)
        {
            IDbConnection iDbConnection;
            
switch (providerType)
            {
                
case DataProvider.SqlServer:
                    iDbConnection 
= new SqlConnection();
                    
break;
                
case DataProvider.OleDb:
                    iDbConnection 
= new OleDbConnection();
                    
break;
                
case DataProvider.Odbc:
                    iDbConnection 
= new OdbcConnection();
                    
break;
                
case DataProvider.Oracle:
                    iDbConnection 
= new OracleConnection();
                    
break;
                
case DataProvider.MySql:
                    iDbConnection 
= new MySqlConnection();
                    
break;
                
default:
                    
return null;
            }
            
return iDbConnection;
        }

        
public static IDbCommand GetCommand(DataProvider providerType)
        {
            
switch (providerType)
            {
                
case DataProvider.SqlServer:
                    
return new SqlCommand();
                
case DataProvider.OleDb:
                    
return new OleDbCommand();
                
case DataProvider.Odbc:
                    
return new OdbcCommand();
                
case DataProvider.Oracle:
                    
return new OracleCommand();
                
case DataProvider.MySql:
                    
return new MySqlCommand();
                
default:
                    
return null;
            }
        }

        
public static IDbDataAdapter GetDataAdapter(DataProvider providerType)
        {
            
switch (providerType)
            {
                
case DataProvider.SqlServer:
                    
return new SqlDataAdapter();
                
case DataProvider.OleDb:
                    
return new OleDbDataAdapter();
                
case DataProvider.Odbc:
                    
return new OdbcDataAdapter();
                
case DataProvider.Oracle:
                    
return new OracleDataAdapter();
                
case DataProvider.MySql:
                    
return new MySqlDataAdapter();
                
default:
                    
return null;
            }
        }

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

        
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.OleDb:
                    
for (int i = 0; i < paramsCount; i++)
                    {
                        idbParams[i] 
= new OleDbParameter();
                    }
                    
break;
                
case DataProvider.Odbc:
                    
for (int i = 0; i < paramsCount; i++)
                    {
                        idbParams[i] 
= new OdbcParameter();
                    }
                    
break;
                
case DataProvider.Oracle:
                    
for (int i = 0; i < paramsCount; i++)
                    {
                        idbParams[i] 
= new OracleParameter();
                    }
                    
break;
                
case DataProvider.MySql:
                    
for (int i = 0; i < paramsCount; i++)
                    {
                        idbParams[i] 
= new MySqlParameter();
                    }
                    
break;
                
default:
                    idbParams 
= null;
                    
break;
            }
            
return idbParams;
        }
    }
}

3、创建一个接口:IDBManager.cs

using System.Data;

namespace DbManager
{
    
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);
    }
}

4、创建一个类来实现IDBManager接口:DBManager.cs

using System;
using System.Data;

namespace 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 DBManager()
        {
        }

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

        
public DBManager(DataProvider providerType, string connectionString)
        {
            ProviderType 
= providerType;
            ConnectionString 
= 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 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;
        }

        
#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.cs,来调用DBManager类,外部来直接调用DBHelper类即可。

using System;
using System.Data;
using System.Configuration;

namespace DbManager
{
    
public class DBHelper
    {
        
private static readonly IDBManager dbManager = new DBManager(GetDataProvider(), GetConnectionString());

        
/// <summary>
        
/// 从配置文件中选择数据库类型
        
/// </summary>
        
/// <returns>DataProvider枚举值</returns>
        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 "OleDb":
                    dataProvider 
= DataProvider.OleDb;
                    
break;
                
case "Odbc":
                    dataProvider 
= DataProvider.Odbc;
                    
break;
                
case "MySql":
                    dataProvider 
= DataProvider.MySql;
                    
break;
                
default:
                    
return DataProvider.Odbc;
            }
            
return dataProvider;
        }

        
/// <summary>
        
/// 从配置文件获取连接字符串
        
/// </summary>
        
/// <returns>连接字符串</returns>
        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, paramName, objValue);
        }

        
/// <summary>
        
/// 执行增删改
        
/// </summary>
        
/// <param name="sqlString">安全的sql语句string.Format()</param>
        
/// <returns>操作成功返回true</returns>
        public static bool ExecuteNonQuery(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">安全的sql语句string.Format()</param>
        
/// <returns>返回IDataReader</returns>
        public static IDataReader ExecuteReader(string sqlString)
        {
            
try
            {
                dbManager.Open();
                
return dbManager.ExecuteReader(CommandType.Text, sqlString);
            }
            
catch (Exception e)
            {
                
throw new Exception(e.Message);
            }
        }
    }
}

现在,将上述项目生成一个DbManager.dll类库,在具体的DAL层里面就可以直接调用了。

DBHelper类没有全部写完,只写了ExecuteNonQuery()和ExecuteReader()两个方法,对于有参和无参的增删改查操作暂时够用,返回DataSet的方法未写,Transaction相关的也未写。

6、app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    
<connectionStrings>
        
<add name="ConnString" connectionString="server=localhost;database=yourDbName;Persist Security Info=False;uid=root;pwd=mysqladmin"/>
        
<!-- 通过改变ConnectionString的值来更换数据库连接字符串
        
<add name="ConnString" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=DBDemo.mdb;Jet OLEDB:Database Password=1234"/>
        
<add name="ConnString" connectionString="server=localhost;database=yourDbName;Persist Security Info=False;Integrated Security=SSPI"/>
        
<add name="ConnString" connectionString="server=localhost;database=yourDbName;Persist Security Info=False;uid=sa;pwd=1234"/>
        
<add name="ConnString" connectionString="server=localhost;database=yourDbName;Persist Security Info=False;uid=root;pwd=mysqladmin"/>
        
-->
    
</connectionStrings>
    
<appSettings>
        
<add key="DataProvider" value="MySql"/>
        
<!-- 通过改变value值来更换数据库
        
<add key="DataProvider" value="Oracle"/>
        
<add key="DataProvider" value="SqlServer"/>
        
<add key="DataProvider" value="OleDb"/>
        
<add key="DataProvider" value="Odbc"/> 
        
<add key="DataProvider" value="MySql"/>
        
-->
    
</appSettings>
</configuration>

7、程序中的调用

举个简单的例子,我们就创建一个控制台应用程序,然后添加DbManager.dll的引用

Program.cs文件的样子:

using System;
using System.Data;
using DbManager;  //记得引入命名空间

namespace DBDemo
{
    
class Program
    {
        
static void Main(string[] args)
        {
            SelectWithoutParams();
            Console.WriteLine(
"------安全sql语句string.Format()的查询结果------");
            SelectWithSafeSql(
4);
            Console.WriteLine(
"------参数化语句的查询结果-------");
            SelectWithParams(
"总统套间");

        }

 

        private static void SelectWithoutParams()

        {
            
const string sql = "select * from RoomType";
            IDataReader reader 
= DBHelper.ExecuteReader(sql);
            
while (reader.Read())
            {
                Console.WriteLine(reader[
"TypeName"].ToString());
            }
            DBHelper.Close();  //记得关闭reader
        }

        
private static void SelectWithSafeSql(int TypeId)
        {
            
string sql = string.Format("select * from RoomType where TypeId={0}", TypeId);
            IDataReader reader 
= DBHelper.ExecuteReader(sql);
            
while (reader.Read())
            {
                Console.WriteLine(reader[
"TypeName"].ToString());
            }
            DBHelper.Close();
        }

        
private static void SelectWithParams(string typeName)
        {

            string sql = "select * from RoomType where TypeName=@TypeName";

 

            //先创建参数,然后才能添加参数 

            DBHelper.CreateParameters(1);  //参数个数,1个
            DBHelper.AddParameters(0"@TypeName", typeName);
            IDataReader reader 
= DBHelper.ExecuteReader(sql);
            
while (reader.Read())
            {
                Console.WriteLine(reader[
"TypeName"].ToString());
            }
            DBHelper.Close();
        }
    }
}

 

OK!全部完成!在具体的DAL层中,调用DBHelper的相关方法即可,如果是查询方法,记得最后要写关闭代码。只要表结构一样,可以在app.config中随意切换数据库。

最后注意的是:

各个数据库的插入语句不一样,假设我们有4个字段,第一个字段fieldName1为自增字段。

对于SQLServer,不需要写自增字段,

语句是:INSERT INTO table VALUES(value2, value3, value4);

对于MySQL,自增字段位置需要写null代替,

语句是:INSERT INTO table VALUES(NULL, value2, value3, value4);

而对于ACCESS数据库,则必须写完整,

语句是:INSERT INTO table(fieldName2, fieldName3,fieldName4) VALUES(value2, value3, value4);

为了实现兼容,大家还是都按完整的来写,就不会有错了。