大家对Dispose模式都比较熟悉了。相信都可以书写较好的Dispose模式的代码。
如下是自己写的一个,开始用起来还不错。到后来需要和其他框架整合使用时,发现一些问题,
比如IBatis中已经OpenConnection,如果我在new ConnectionHelper()时,应该引用已有的数据库连接对象。
但该对象又不应该由我来释放,而是由IBatis来负责释放。
当我们的非托管资源是由其他对象管理,而我们只是借用时,要确保该非托管资源的管理不是我的职责,
我们不应该越权去管理这些非托管资源。
只要记住一条:冤有头,债有主,谁创建的非托管资源就由谁去收拾吧!
因此如下的实现类中增加了一个标示:
/// <summary>
/// 标示是否是当前对象的职责去释放非托管资源。本着谁创建谁释放的原则进行设计
/// </summary>
private bool fIsMyResponsibilityToDispose = true;
当我们基于其他资源创建该对象时,就把上述标示设置为false.
-----------------------------------------------------------------------------------------------
using System;
using System.Data;
using System.Collections.Generic;
namespace AppleXml
{
/// <summary>
/// 数据库连接辅助类
/// 目前支持SqlServer,Oracle,Excel的处理
/// </summary>
public class ConnectionHelper : IConnectionHelper
{
private static Dictionary<string, DataBaseVersion> fConnectionVersions = null;
private static string fDefaultConnectionString = string.Empty;
private static DataBaseVersion fDefaultDataBaseVersion;
static ConnectionHelper()
{
fConnectionVersions = new Dictionary<string, DataBaseVersion>();
fDefaultConnectionString = string.Empty;
fDefaultDataBaseVersion = DataBaseVersion.SqlServer2005;
}
/// <summary>
/// 获取新的默认的连接串对应的ConnectionHelper对象
/// </summary>
/// <returns></returns>
public static IConnectionHelper GetNewDefaultConnectionHelper()
{
if (DataUtility.InvalidString(fDefaultConnectionString))
{
throw new Exception("请设置ConnectionHelper.DefaultConnectionString");
}
return new ConnectionHelper(fDefaultConnectionString);
}
/// <summary>
/// 测试指定的数据库连接是否有效,成功返回true,否则返回false
/// </summary>
/// <param name="connectionString"></param>
/// <returns></returns>
public static bool TestConnection(string connectionString)
{
IConnectionHelper ch = null;
try
{
ch = new ConnectionHelper(connectionString);
ch.Connection.Open();
ch.Connection.Close();
return true;
}
catch
{
return false;
}
finally
{
if (ch != null)
{
ch.Dispose();
}
}
}
/// <summary>
/// 测试指定的数据库设置对象是否有效,成功返回true,否则返回false
/// </summary>
/// <param name="dbSettingInfo"></param>
/// <returns></returns>
public static bool TestConnection(DataBaseSettingInfo dbSettingInfo)
{
return TestConnection(dbSettingInfo.GetConnectionString());
}
private string fConnectionString = string.Empty;
private bool fIsInTransaction = false;
private IDbConnection fConnection = null;
private IDbTransaction fTransaction = null;
/// <summary>
/// 标示是否是当前对象的职责去释放非托管资源。本着谁创建谁释放的原则进行设计
/// </summary>
private bool fIsMyResponsibilityToDispose = true;
/// <summary>
/// 标记是否已经释放了资源
/// </summary>
private bool fHasDispose = false;
/// <summary>
/// 这个采用默认的连接字符串。(通过静态构造函数从配置文件中取出来的)
/// </summary>
public ConnectionHelper()
{
if (DataUtility.InvalidString(fDefaultConnectionString))
{
throw new DataBaseNotSetDefaultConnectionStringException();
}
fConnectionString = fDefaultConnectionString;
fIsMyResponsibilityToDispose = true;
}
/// <summary>
/// 这个需要自己设置当前的连接字符串,因为有时候会涉及到多个数据库的操作
/// </summary>
/// <param name="connectionString"></param>
public ConnectionHelper(string connectionString)
{
if (DataUtility.InvalidString(connectionString))
{
throw new Exception("connectionString不能为空");
}
fConnectionString = connectionString;
fIsMyResponsibilityToDispose = true;
}
/// <summary>
/// 根据现有的IDbConnection对象创建ConnectionHelper对象
/// </summary>
/// <param name="conn"></param>
public ConnectionHelper(IDbConnection conn)
{
if (conn == null)
{
throw new ArgumentNullException("conn");
}
fConnection = conn;
fIsMyResponsibilityToDispose = false;
}
/// <summary>
/// 根据现有的IDbTransaction创建ConnectionHelper对象
/// </summary>
/// <param name="trans"></param>
public ConnectionHelper(IDbTransaction trans)
{
if (trans == null)
{
throw new ArgumentNullException("trans");
}
fConnection = trans.Connection;
fTransaction = trans;
fIsInTransaction = true;
fIsMyResponsibilityToDispose = false;
}
/// <summary>
/// [获取/设置]默认的连接字符串,同时设置数据库的版本
/// </summary>
public static string DefaultConnectionString
{
get
{
return fDefaultConnectionString;
}
set
{
fDefaultConnectionString = value;
if (!DataUtility.InvalidString(fDefaultConnectionString))
{
using (IConnectionHelper ch = new ConnectionHelper())
{
fDefaultDataBaseVersion = DataBaseUtility.GetDataBaseVersion(ch);
}
}
else
{
throw new DataBaseNotSetDefaultConnectionStringException();
}
}
}
/// <summary>
/// [获取]当前连接对象
/// </summary>
public IDbConnection Connection
{
get
{
if (fConnection == null)
{
fConnection = DataBaseUtility.NewConnection(fConnectionString);
}
return fConnection;
}
}
/// <summary>
/// [获取]当前事务对象
/// </summary>
public IDbTransaction Transaction
{
get
{
return fTransaction;
}
}
/// <summary>
/// [获取]是否正在事务中运行,true表示是,false表示否
/// </summary>
public bool IsInTransaction
{
get
{
return fIsInTransaction;
}
}
/// <summary>
/// [获取]数据库类型
/// </summary>
public DataBaseType DataBaseType
{
get
{
return DataBaseUtility.GetDataBaseType(Connection);
}
}
/// <summary>
/// [获取]数据库版本
/// </summary>
public DataBaseVersion DataBaseVersion
{
get
{
if (!fConnectionVersions.ContainsKey(fConnectionString))
{
fConnectionVersions.Add(fConnectionString, DataBaseUtility.GetDataBaseVersion(this));
}
return fConnectionVersions[fConnectionString];
}
}
/// <summary>
/// [获取]当前数据库参数化时前缀的字符,比如Sql的@,Oracle的:
/// </summary>
public string ParameterPrefix
{
get
{
return DataUtility.GetParameterPrefix(this);
}
}
/// <summary>
/// [获取]当前数据库有效对象名的左边界
/// </summary>
public string ObjectLeftMark
{
get
{
switch (DataBaseType)
{
case DataBaseType.SqlServer:
return "[";
}
return string.Empty;
}
}
/// <summary>
/// [获取]当前数据库有效对象名的右边界
/// </summary>
public string ObjectRightMark
{
get
{
switch (DataBaseType)
{
case DataBaseType.SqlServer:
return "]";
}
return string.Empty;
}
}
/// <summary>
/// 准备开始事务,如果开始成功返回true,否则false
/// </summary>
/// <returns></returns>
public bool BeginTransaction()
{
return BeginTransaction(IsolationLevel.ReadCommitted);
}
/// <summary>
/// 准备开始事务,如果开始成功返回true,否则false,可以指定隔离级别
/// </summary>
/// <returns></returns>
public bool BeginTransaction(IsolationLevel level)
{
if (fIsInTransaction)
{
return false;
}
DataUtility.OpenConnection(Connection);
fTransaction = Connection.BeginTransaction();
fIsInTransaction = true;
return true;
}
/// <summary>
/// 回滚事务,成功 返回true
/// </summary>
/// <returns></returns>
public bool RollbackTransaction()
{
if (fIsInTransaction)
{
if (fTransaction != null)
{
fTransaction.Rollback();
}
fIsInTransaction = false;
return true;
}
return false;
}
/// <summary>
/// 提交事务,成功 返回true
/// </summary>
/// <returns></returns>
public bool CommitTransaction()
{
if (fIsInTransaction)
{
if (fTransaction != null)
{
fTransaction.Commit();
}
fIsInTransaction = false;
return true;
}
else
{
return false;
}
}
/// <summary>
/// 终结器,在用户忘记时,调用之
/// </summary>
~ConnectionHelper()
{
Dispose(false);
}
public void Close()
{
Dispose();
}
/// <summary>
/// 用户调用的处理。
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// 一般在派生类中调用,不是当前对象的职责或者已经释放过了,则不需要再次释放
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
//不是当前对象的职责或者已经释放过了,则不需要再次释放
if (!fIsMyResponsibilityToDispose || fHasDispose)
{
return;
}
if (disposing)
{
//用户调用时的处理
if (fTransaction != null)
{
fTransaction.Dispose();
fTransaction = null;
}
if (fConnection != null)
{
fConnection.Close();
fConnection = null;
}
}
fHasDispose = true;
}
/// <summary>
/// [获取]数据库帮助类。采用这里的帮助对象可以获得最大限度的缓存效果
/// </summary>
public IDataBaseHelper DataBaseHelper
{
get
{
IDataBaseHelper dbh = new DataBaseFactory();
return dbh;
}
}
/// <summary>
/// 获取安全的对象名(包括表、字段等,比如SqlServer则用[]括起来)
/// </summary>
/// <param name="objectName"></param>
/// <returns></returns>
public string GetSafetyObjectName(string objectName)
{
if (DataUtility.InvalidString(objectName))
{
throw new Exception("数据库对象名称不能为空");
}
objectName = objectName.Trim();
if (objectName.StartsWith("[") && objectName.EndsWith("]"))
{
return objectName;
}
return string.Format("{0}{1}{2}", ObjectLeftMark, objectName, ObjectRightMark);
}
}
}