大多数数据库接口依赖于某些数据库连接对象,它们好像应用程序代码和数据库之间的桥梁。通常,一个连接必须在执行数据库操作命令之前就要打开。实际上,经常需要一个显示连接来建立和执行命令。在命令执行的整个过程中,该连接必须是打开的,查询的结果将返回一个记录集,才关闭数据库连接。如果正在一个事务中运行,经常会把事务绑定在特定的连接上,当它运行的时候这个连接也必须一直打开,直到这个事务结束才能关闭连接。
在很多环境中,建立连接的开销相当大,这就需要建立一个连接池。在这种情况下,开发者向连接池请求一个连接并在完成以后释放,而无需即时创建和关闭。注意这里不是要你自己去创建连接池,因为现在多数平台都会提供连接池,所以很少需要自己来实现连接池。如果必须自己实现连接池,首先就要检查连接池是不是真的能提高性能(对连接池的创建可以参考后面的代码【1】)。还要注意:越来越多的环境使我们可以更快地创建新的连接,因此也不需要使用缓冲池。
提供连接池的环境把连接池放在一个类似创建新连接的接口后面。用这种方法,无需知道得到得是一个新创建连接还是从连接池里面分配的。类似地,关闭一个连接可能并没有真正关闭它,而只是把它替换为从连接池获取和释放。
无论创建连接的代价是高还是低,连接都必须好好管理,因为它们是珍贵的资源,必须在使用完毕时立刻关闭。还有,如果正在进行一次事务,通常需要保证:在这次特定的事务中,每一个命令都是从同一个连接发出的。
最常见的建议就是用一个到连接池或者连接管理器的调用,显示得到一个连接,并且通过它来执行数据库命令,一旦执行完了,立刻把它关闭。这个建议带来两个问题:首先,保证在任何需要的地方都能得到一个连接;其次,保证不会在最后忘记关闭它(可以参考后面得示例代码【2】)。
现代环境提供了自动的内存管理和垃圾回收机制,因此保证连接关闭的一种方法就是使用垃圾回收器。在这种方式下,连接自身或者引用这个连接的对象会在垃圾回收期间关闭连接。这样做的好处是:它使用了和内存管理相同的机制,同样方便,也不陌生。这样做的问题是:连接的关闭只有当垃圾回收器实际回收内存的时候才发生,可能离这个连接失去它最后一次引用的时间已经很久了,结果是未被引用的连接可能会隔一段时间才被关闭。总的来说,我不喜欢依赖垃圾回收机制,对于其它的机制,甚至是显示关闭都会好一些。当然,垃圾回收机制在其它机制失败的情况下还是一种很好的后备。
连接管理细节描述的往往是数据库交互软件的特征,因此所使用的策略通常是由环境来决定的。
连接池的创建示例代码【1】:
using System;
using System.Timers;
using System.Collections;
using System.Data.SqlClient;
using Common;

namespace SqlDBConnection

...{

/**//// <summary>
/// DBConnection 的数据库连接对象池。
/// </summary>
public sealed class DBConnection : ObjectPool

...{
private DBConnection()

...{
}

public static readonly DBConnection Instance = new DBConnection();

private static string _connectionstring = "数据库连接字符串";

public static string Connectionstring

...{
set

...{
_connectionstring = value;
}
get

...{
return _connectionstring;
}
}

protected override object Create()

...{
try

...{
SqlConnection temp = new SqlConnection(_connectionstring);
temp.Open();
return (temp);
}
catch

...{
return null;
}
}

protected override bool Validate(object o)

...{
try

...{
SqlConnection temp = (SqlConnection)o;
return (!((temp.State.Equals(System.Data.ConnectionState.Closed))));
}
catch (SqlException)

...{
return false;
}
}

protected override void Expire(object o)

...{
try

...{
((SqlConnection)o).Close();
}
catch (SqlException)

...{
}
}

public SqlConnection BorrowDBConnection()

...{
try

...{
return ((SqlConnection)base.GetObjectFromPool());
}
catch (Exception e)

...{
throw e;
}
}

public void ReturnDBConnection(SqlConnection c)

...{
base.ReturnObjectToPool(c);
}
}


/**//// <summary>
/// ObjectPool 的对象池。
/// </summary>
public abstract class ObjectPool

...{
private long _lastCheckOut;
private static Hashtable locked;
private static Hashtable unlocked;
internal static long CARBAGE_INTERVAL = 9 * 1000;

static ObjectPool()

...{
locked = Hashtable.Synchronized(new Hashtable());
unlocked = Hashtable.Synchronized(new Hashtable());
}

internal ObjectPool()

...{
_lastCheckOut = DateTime.Now.Ticks;
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Enabled = true;
aTimer.Interval = CARBAGE_INTERVAL;
aTimer.Elapsed += new System.Timers.ElapsedEventHandler(CollectGarbage);
}

protected abstract object Create();

protected abstract bool Validate(object o);

protected abstract void Expire(object o);

internal object GetObjectFromPool()

...{
long now = DateTime.Now.Ticks;
_lastCheckOut = now;
object o = null;
o = Create();
locked.Add(o, now);
return (o);
}

internal void ReturnObjectToPool(object o)

...{
if (o != null)

...{
lock (this)

...{
locked.Remove(o);
unlocked.Add(o, DateTime.Now.Ticks);
}
}
}

private void CollectGarbage(object sender, System.Timers.ElapsedEventArgs ea)

...{
lock (this)

...{
object o;
long now = DateTime.Now.Ticks;
IDictionaryEnumerator e = unlocked.GetEnumerator();

try

...{
while (e.MoveNext())

...{
o = e.Key;
if ((now - ((long)unlocked[o])) > CARBAGE_INTERVAL)

...{
unlocked.Remove(o);
Expire(o);
o = null;
}
}
}

catch (Exception) ...{ }
}
}
}
}
数据库连接示例代码【2】:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using SqlDBConnection;
using Common;

namespace MyMedia_Competitor

...{

/**//// <summary>
/// SqlDataBase 的摘要说明。
/// </summary>
public class MySqlDataBase

...{

/**//// <summary>
/// 构造函数
/// </summary>
public MySqlDataBase()

...{
}
public DBConnection Connection;


/**//// <summary>
/// 获取数据库连接接口
/// </summary>
public IDbConnection GetConnection()

...{
IDbConnection sqlConnection1 = null;
string connectionstring = "数据库连接字符串";
sqlConnection1 = (IDbConnection)new SqlConnection(connectionstring);
sqlConnection1.Open();
return sqlConnection1;
}


/**//// <summary>
/// 将数据库连接接口返回连接池
/// </summary>
public void ReturnConnection(SqlConnection obj)

...{
Connection.ReturnDBConnection(obj);
}


/**//// <summary>

/// 根据数据库类型获取数据库命令接口
/// </summary>
/// <param name="sqlstr">数据库命令字符串</param>
/// <param name="sqlConnection1">数据库连接接口</param>
/// <returns>数据库命令接口</returns>
/// </summary>
private IDbCommand GetCommand(string sqlstr, IDbConnection sqlConnection1)

...{
IDbCommand sqlCommand1 = null;
sqlCommand1 = new SqlCommand(sqlstr, (SqlConnection)sqlConnection1);
sqlCommand1.CommandTimeout = 99999999;
return sqlCommand1;
}


/**//// <summary>
/// 根据数据库类型获取数据适配器接口
/// <param name="sqlCommand1">数据库命令接口</param>
/// <returns>数据适配器接口</returns>
private IDataAdapter GetDataAdapter(IDbCommand sqlCommand1)

...{
IDataAdapter sqlDataAdapter1 = null;
sqlDataAdapter1 = new SqlDataAdapter((SqlCommand)sqlCommand1);
DataAdapte = sqlDataAdapter1;
return sqlDataAdapter1;
}


/**//// <summary>
/// 数据适配器属性
/// </summary>
IDataAdapter DataAdapte = null;

private IDataAdapter DataAdapter

...{
get

...{
return DataAdapte;
}
}


/**//// <summary>
/// 下面是处理数据,返回结果集
/// </summary>
// 1.

/**//// <summary>
/// 执行SQL语句并返回受影响的行的数目
/// <param name="sqlstr">数据库命令字符串</param>
/// <returns>受影响的行的数目</returns>
/// </summary>
public int ExecuteNonQuery(string sqlstr)

...{
IDbConnection sqlConnection1 = null;
IDbCommand sqlCommand1 = null;
try

...{
sqlConnection1 = this.GetConnection();
sqlCommand1 = this.GetCommand(sqlstr, sqlConnection1);
return sqlCommand1.ExecuteNonQuery();
}
catch (Exception ex)

...{
System.Diagnostics.Debug.WriteLine(ex.Message);
return 0;
}
finally

...{
if (sqlCommand1 != null)
sqlCommand1.Dispose();

if (sqlConnection1 != null)
sqlConnection1.Close();
// Connection.ReturnDBConnection((SqlConnection)sqlConnection1);
}
}
// 2.

/**//// <summary>
/// 执行SQL语句并返回数据行
/// <param name="sqlstr">数据库命令字符串</param>
/// <returns>数据读取器接口</returns>
/// </summary>
public SqlDataReader ExecuteReader(string sqlstr)

...{
IDbConnection sqlConnection1 = null;
IDbCommand sqlCommand1 = null;
try

...{
sqlConnection1 = this.GetConnection();
sqlCommand1 = this.GetCommand(sqlstr, sqlConnection1);
return (SqlDataReader)sqlCommand1.ExecuteReader(CommandBehavior.CloseConnection);
}
catch (Exception ex)

...{
System.Diagnostics.Debug.WriteLine(ex.Message);
return null;
}
finally

...{
if (sqlCommand1 != null)
sqlCommand1.Dispose();

if (sqlConnection1 != null)
sqlConnection1.Close();

// Connection.ReturnDBConnection((SqlConnection)sqlConnection1);
}
}
// 3.

/**//// <summary>
/// 执行SQL语句并返回单值对象
/// 即结果集中第一行的第一条数据
/// <param name="sqlstr">数据库命令字符串</param>
/// <returns>单值对象-结果集中第一行的第一条数据</returns>
/// </summary>
public object ExecuteScalar(string sqlstr)

...{
IDbConnection sqlConnection1 = null;
IDbCommand sqlCommand1 = null;
try

...{
sqlConnection1 = this.GetConnection();
sqlCommand1 = this.GetCommand(sqlstr, sqlConnection1);
return sqlCommand1.ExecuteScalar();
}
catch (Exception ex)

...{
System.Diagnostics.Debug.WriteLine(ex.Message);
return null;
}
finally

...{
if (sqlCommand1 != null)
sqlCommand1.Dispose();

if (sqlConnection1 != null)
sqlConnection1.Close();

// Connection.ReturnDBConnection((SqlConnection)sqlConnection1);
}
}
// 4.

/**//// <summary>
/// 填充一个数据集对象并返回之
/// <param name="sqlstr">数据库命令字符串</param>
/// <returns>数据集对象</returns>
/// </summary>
public DataSet GetDataSet(string sqlstr)

...{
IDbConnection sqlConnection1 = null;
IDbCommand sqlCommand1 = null;
IDataAdapter sqlDataAdapter1 = null;
DataSet ds = null;
try

...{
sqlConnection1 = this.GetConnection();
sqlCommand1 = this.GetCommand(sqlstr, sqlConnection1);
sqlDataAdapter1 = this.GetDataAdapter(sqlCommand1);
ds = new DataSet();
sqlDataAdapter1.Fill(ds);
return ds;
}
catch (Exception ex)

...{
System.Diagnostics.Debug.WriteLine(ex.Message);
return null;
}
finally

...{
if (sqlCommand1 != null)
sqlCommand1.Dispose();

if (sqlConnection1 != null)
sqlConnection1.Close();

//Connection.ReturnDBConnection((SqlConnection)sqlConnection1);
}
}
// 5.

/**//// <summary>
/// 执行存储过程
/// <param name="StoredStr">存储过程名</param>
/// <param name="arrParams">所要传入的参数</param>
/// <returns>数据集对象</returns>
/// </summary>
public DataSet GetDataSetForStored(string StoredStr, SqlParameter[] arrParams)

...{
IDbConnection sqlConnection1 = null;
IDbCommand sqlCommand1 = null;
IDataAdapter sqlDataAdapter1 = null;
DataSet ds = null;
try

...{
sqlConnection1 = this.GetConnection();
sqlCommand1 = this.GetCommand(StoredStr, sqlConnection1);
sqlCommand1.CommandType = CommandType.StoredProcedure;
for (int i = 0; i < arrParams.Length; i++)

...{
sqlCommand1.Parameters.Add(arrParams[i]);
}

sqlDataAdapter1 = this.GetDataAdapter(sqlCommand1);

ds = new DataSet();
sqlDataAdapter1.Fill(ds);
return ds;
}
catch (Exception ex)

...{
System.Diagnostics.Debug.WriteLine(ex.Message);
return null;
}
finally

...{
if (sqlCommand1 != null)
sqlCommand1.Dispose();

if (sqlConnection1 != null)
sqlConnection1.Close();
// Connection.ReturnDBConnection((SqlConnection)sqlConnection1);
}
}
// 6.

/**//// <summary>
/// 执行存储过程
/// <param name="StoredStr">存储过程名</param>
/// <param name="arrParams">所要传入的参数</param>
/// <returns>数据集对象</returns>
/// </summary>
public void RunStored(string StoredStr, SqlParameter[] arrParams)

...{
IDbConnection sqlConnection1 = null;
IDbCommand sqlCommand1 = null;
try

...{
sqlConnection1 = this.GetConnection();
sqlCommand1 = this.GetCommand(StoredStr, sqlConnection1);
sqlCommand1.CommandType = CommandType.StoredProcedure;
for (int i = 0; i < arrParams.Length; i++)

...{
sqlCommand1.Parameters.Add(arrParams[i]);
}
sqlCommand1.ExecuteNonQuery();
}
catch (Exception ex)

...{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
finally

...{
if (sqlCommand1 != null)
sqlCommand1.Dispose();

if (sqlConnection1 != null)
sqlConnection1.Close();

//Connection.ReturnDBConnection((SqlConnection)sqlConnection1);
}
}
}
}


/**//// <summary>
/// 还可以继续扩张
/// </summary>