程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> DBHelper (支持事務與數據庫變更),dbhelper事務

DBHelper (支持事務與數據庫變更),dbhelper事務

編輯:C#入門知識

DBHelper (支持事務與數據庫變更),dbhelper事務


1   概述

更新內容:添加 "支持數據分頁"

這個數據庫操作類的主要特色有

1>     事務操作更加的方便

2>     變更數據庫更加的容易

3>   支持數據分頁

最新的所有代碼:

using System; using System.Data; using System.Data.Common; using Project.BaseFramework; using System.Collections.Generic; using System.Configuration; namespace Project.BaseFramework.DataProvider { public class DBHelper { #region Constuctor public DBHelper() { } private static string ConnectionString = ConfigurationManager.AppSettings["DBConnectionString"]; private static IDBClient DBClient = DBClientFactory.GetDBClient(ConfigurationManager.AppSettings["DBClient"]); [ThreadStatic] private static TransConnection TransConnectionObj = null; #endregion #region ExecuteNonQuery public static int ExecuteNonQuery(CommandType cmdType, string cmdText, params DbParameter[] parameterValues) { int result = 0; bool mustCloseConn = true; DbCommand cmd = PrepareCmd(cmdType, cmdText, parameterValues, out mustCloseConn); OpenConn(cmd.Connection); result = cmd.ExecuteNonQuery(); if (mustCloseConn) CloseConn(cmd.Connection); ClearCmdParameters(cmd); cmd.Dispose(); return result; } #endregion ExecuteNonQuery #region ExecuteScalar public static object ExecuteScalar(CommandType cmdType, string cmdText, params DbParameter[] parameterValues) { object result = 0; bool mustCloseConn = true; DbCommand cmd = PrepareCmd(cmdType, cmdText, parameterValues, out mustCloseConn); OpenConn(cmd.Connection); result = cmd.ExecuteScalar(); if (mustCloseConn) CloseConn(cmd.Connection); ClearCmdParameters(cmd); cmd.Dispose(); return result; } #endregion ExecuteScalar #region ExecuteReader public static DbDataReader ExecuteReader(CommandType cmdType, string cmdText, params DbParameter[] parameterValues) { DbDataReader result = null; bool mustCloseConn = true; DbCommand cmd = PrepareCmd(cmdType, cmdText, parameterValues, out mustCloseConn); try { OpenConn(cmd.Connection); if (mustCloseConn) { result = cmd.ExecuteReader(CommandBehavior.CloseConnection); } else { result = cmd.ExecuteReader(); } ClearCmdParameters(cmd); return result; } catch (Exception ex) { if (mustCloseConn) CloseConn(cmd.Connection); ClearCmdParameters(cmd); cmd.Dispose(); throw ; } } #endregion ExecuteReader #region ExecuteDataset public static DataSet ExecuteDataSet(CommandType cmdType, string cmdText, params DbParameter[] parameterValues) { DataSet result = null; bool mustCloseConn = true; DbCommand cmd = PrepareCmd(cmdType, cmdText, parameterValues, out mustCloseConn); using (DbDataAdapter da = DBClient.GetDbDataAdappter()) { da.SelectCommand = cmd; result = new DataSet(); da.Fill(result); } if (mustCloseConn) CloseConn(cmd.Connection); ClearCmdParameters(cmd); cmd.Dispose(); return result; } #endregion ExecuteDataset #region ExecuteDataTable public static DataTable ExecuteDataTable(CommandType cmdType, string cmdText, params DbParameter[] parameterValues) { DataSet ds = ExecuteDataSet(cmdType,cmdText, parameterValues); if (ds != null && ds.Tables.Count > 0) return ds.Tables[0]; else return null; } #endregion #region ExecutePaging public static DataTable ExecutePagingDataTable(CommandType cmdType, string cmdText,int pageIndex,int pageSize,string orderInfo, params DbParameter[] parameterValues) { cmdText = DBClient.GetPagingSql(cmdText, pageIndex, pageSize, orderInfo); return ExecuteDataTable(CommandType.Text, cmdText, parameterValues); } public static DbDataReader ExecutePagingReader(CommandType cmdType, string cmdText, int pageIndex, int pageSize, string orderInfo, params DbParameter[] parameterValues) { cmdText = DBClient.GetPagingSql(cmdText, pageIndex, pageSize, orderInfo); return ExecuteReader(CommandType.Text, cmdText, parameterValues); } #endregion #region Transaction public static void BeginTransaction() { if (TransConnectionObj == null) { DbConnection conn = DBClient.GetDbConnection(ConnectionString); OpenConn(conn); DbTransaction trans = conn.BeginTransaction(); TransConnectionObj = new TransConnection(); TransConnectionObj.DBTransaction = trans; } else { TransConnectionObj.Deeps += 1; } } public static void CommitTransaction() { if (TransConnectionObj == null) return; if (TransConnectionObj.Deeps > 0) { TransConnectionObj.Deeps -= 1; } else { TransConnectionObj.DBTransaction.Commit(); ReleaseTransaction(); } } public static void RollbackTransaction() { if (TransConnectionObj == null) return; if (TransConnectionObj.Deeps > 0) { TransConnectionObj.Deeps -= 1; } else { TransConnectionObj.DBTransaction.Rollback(); ReleaseTransaction(); } } private static void ReleaseTransaction() { if (TransConnectionObj == null) return; DbConnection conn = TransConnectionObj.DBTransaction.Connection; TransConnectionObj.DBTransaction.Dispose(); TransConnectionObj = null; CloseConn(conn); } #endregion #region Connection private static void OpenConn(DbConnection conn) { if (conn == null) conn = DBClient.GetDbConnection(ConnectionString); if (conn.State == ConnectionState.Closed) conn.Open(); } private static void CloseConn(DbConnection conn) { if (conn == null) return; if (conn.State == ConnectionState.Open) conn.Close(); conn.Dispose(); conn = null; } #endregion #region Create DbParameter public static DbParameter CreateInDbParameter(string paraName, DbType type, int size, object value) { return CreateDbParameter(paraName, type, size, value, ParameterDirection.Input); } public static DbParameter CreateInDbParameter(string paraName, DbType type, object value) { return CreateDbParameter(paraName, type, 0, value, ParameterDirection.Input); } public static DbParameter CreateOutDbParameter(string paraName, DbType type, int size) { return CreateDbParameter(paraName, type, size, null, ParameterDirection.Output); } public static DbParameter CreateOutDbParameter(string paraName, DbType type) { return CreateDbParameter(paraName, type, 0, null, ParameterDirection.Output); } public static DbParameter CreateReturnDbParameter(string paraName, DbType type, int size) { return CreateDbParameter(paraName, type, size, null, ParameterDirection.ReturnValue); } public static DbParameter CreateReturnDbParameter(string paraName, DbType type) { return CreateDbParameter(paraName, type, 0, null, ParameterDirection.ReturnValue); } public static DbParameter CreateDbParameter(string paraName, DbType type, int size, object value, ParameterDirection direction) { DbParameter para = DBClient.GetDbParameter(); para.ParameterName = paraName; if (size != 0) { para.Size = size; } para.DbType = type; if (value != null) { para.Value = value; } else { para.Value = DBNull.Value; } para.Direction = direction; return para; } #endregion #region Command and Parameter /// <summary> /// 預處理用戶提供的命令,數據庫連接/事務/命令類型/參數 /// </summary> /// <param>要處理的DbCommand</param> /// <param>數據庫連接</param> /// <param>一個有效的事務或者是null值</param> /// <param>命令類型 (存儲過程,命令文本, 其它.)</param> /// <param>存儲過程名或都T-SQL命令文本</param> /// <param>和命令相關聯的DbParameter參數數組,如果沒有參數為'null'</param> /// <param><c>true</c> 如果連接是打開的,則為true,其它情況下為false.</param> private static DbCommand PrepareCmd(CommandType cmdType,string cmdText, DbParameter[] cmdParams, out bool mustCloseConn) { DbCommand cmd = DBClient.GetDbCommand(cmdText); DbConnection conn = null; if (TransConnectionObj != null) { conn = TransConnectionObj.DBTransaction.Connection; cmd.Transaction = TransConnectionObj.DBTransaction; mustCloseConn = false; } else { conn = DBClient.GetDbConnection(ConnectionString); mustCloseConn = true; } cmd.Connection = conn; cmd.CommandType = cmdType; AttachParameters(cmd, cmdParams); return cmd; } /// <summary> /// 將DbParameter參數數組(參數值)分配給DbCommand命令. /// 這個方法將給任何一個參數分配DBNull.Value; /// 該操作將阻止默認值的使用. /// </summary> /// <param>命令名</param> /// <param>SqlParameters數組</param> private static void AttachParameters(DbCommand command, DbParameter[] commandParameters) { if (command == null) throw new ArgumentNullException("command"); if (commandParameters != null) { foreach (DbParameter p in commandParameters) { if (p != null) { // 檢查未分配值的輸出參數,將其分配以DBNull.Value. if ((p.Direction == ParameterDirection.InputOutput || p.Direction == ParameterDirection.Input) && (p.Value == null)) { p.Value = DBNull.Value; } command.Parameters.Add(p); } } } } private static void ClearCmdParameters(DbCommand cmd) { bool canClear = true; if (cmd.Connection != null && cmd.Connection.State != ConnectionState.Open) { foreach (DbParameter commandParameter in cmd.Parameters) { if (commandParameter.Direction != ParameterDirection.Input) { canClear = false; break; } } } if (canClear) { cmd.Parameters.Clear(); } } #endregion } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Common; namespace Project.BaseFramework.DataProvider { internal class TransConnection { public TransConnection() { this.Deeps = 0; } public DbTransaction DBTransaction { get; set; } public int Deeps { get; set; } } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Common; using System.Data.SqlClient; namespace Project.BaseFramework.DataProvider { public interface IDBClient { DbConnection GetDbConnection(string connectionString); DbCommand GetDbCommand(string cmdText); DbDataAdapter GetDbDataAdappter(); DbParameter GetDbParameter(); string GetPagingSql(string cmdText, int pageIndex, int pageSize, string orderInfo); } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Common; using System.Data.SqlClient; namespace Project.BaseFramework.DataProvider { public class SqlServerClient:IDBClient { public DbConnection GetDbConnection(string connectionString) { return new SqlConnection(connectionString); } public DbCommand GetDbCommand(string cmdText) { return new SqlCommand(cmdText); } public DbDataAdapter GetDbDataAdappter() { return new SqlDataAdapter(); } public DbParameter GetDbParameter() { return new SqlParameter(); } public string GetPagingSql(string cmdText, int pageIndex, int pageSize, string orderInfo) { int startIndex = (pageIndex - 1) * pageSize; int endIndex = startIndex + pageSize + 1; cmdText = string.Format(@";WITH T1 AS({0}),T2 AS(SELECT *,ROW_NUMBER()OVER ({1}) AS _RowNum FROM T1) SELECT *FROM T2 WHERE _RowNum>{2} AND _RowNum<{3}",cmdText,orderInfo,startIndex,endIndex); return cmdText; } } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Common; using MySql.Data.MySqlClient; namespace Project.BaseFramework.DataProvider { public class MySqlClient:IDBClient { public DbConnection GetDbConnection(string connectionString) { return new MySqlConnection(connectionString); } public DbCommand GetDbCommand(string cmdText) { return new MySqlCommand(cmdText); } public DbDataAdapter GetDbDataAdappter() { return new MySqlDataAdapter(); } public DbParameter GetDbParameter() { return new MySqlParameter(); } public string GetPagingSql(string cmdText, int pageIndex, int pageSize, string orderInfo) { int startIndex = (pageIndex - 1) * pageSize; cmdText = string.Format(@"{0} {1} Limit {2}, {3}", cmdText, orderInfo, startIndex,pageSize); return cmdText; } } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Configuration; using System.Reflection; namespace Project.BaseFramework.DataProvider { public class DBClientFactory { private static readonly string path = "Project.BaseFramework"; public static IDBClient GetDBClient(string dbClientClassName) { if(string.IsNullOrEmpty(dbClientClassName)) dbClientClassName="SqlServerClient"; string className = string.Format("{0}.DataProvider.{1}", path, dbClientClassName); return (IDBClient)Assembly.Load(path).CreateInstance(className); } } } View Code

配置文件

<appSettings>
    <add key="DBConnectionString" value="Data Source=.;Initial Catalog=ProjectData;Persist Security Info=True;User ID=sa;Password=kjkj,911;"/>
    <add key="DBClient" value="SqlServerClient"/>
</appSettings>

 

 

2  事務操作

2.1 單個事務操作示例

復制代碼
try
{
    DBHelper.BeginTransaction();
    // add 
    DBHelper.ExecuteNonQuery(CommandType.Text, "INSERT INTO TRole(ID,RoleName) VALUES('R1','MKT')");

    //detele by pk
    DBHelper.ExecuteNonQuery(CommandType.Text, "DELETE FROM TRole WHERE ID='R1'");

    Console.WriteLine(string.Format("Success and Commited"));
    DBHelper.CommitTransaction();
}
catch (Exception ex)
{
    Console.WriteLine(string.Format("Exception and rollback"));
    DBHelper.RollbackTransaction();
}
復制代碼

 

用法是:只需要把相關聯的代碼放在BeginTransaction和CommitTransaction中間,如果發生異常調用RollbackTransaction即可。

實現事務的方法是:

首先,DBHelper維護一個TransConnection類型的字段,並添加ThreadStatic. ThreadStatic可以維護在線程級別上的唯一性。

[ThreadStatic]
private static TransConnection TransConnectionObj = null;

 

其次,TransConnection的作用是保存事務,並記錄嵌套事務的嵌套級別。

復制代碼
internal class TransConnection
{
    public TransConnection()
    {
        this.Deeps = 0;
    }

    public DbTransaction DBTransaction { get; set; }

    public int Deeps { get; set; }
}
復制代碼

 

最後,當調用 BeginTransaction時創建TransConnection對象。之後的多個DbCommand命令都從這個事務上拿連接。因為TransConnectionObj添加了ThreadStatic屬性,所以它是線程唯一的,不會影響其它線程上的事務;所有方法執行完後,調用CommitTransaction 就提交事務,並關閉連接;如果發生異常,則調用RollbackTransaction,就會回滾所有命令,並關閉連接。

2.2 嵌套事務示例

復制代碼
static void Main(string[] args)
{

    try
    {
        DBHelper.BeginTransaction();

        // add 
        DBHelper.ExecuteNonQuery(CommandType.Text, "INSERT INTO TRole(ID,RoleName) VALUES('R1','MKT')");

        Transaction2();

        //detele by pk
        DBHelper.ExecuteNonQuery(CommandType.Text, "DELETE FROM TRole WHERE ID='R1'");

        Console.WriteLine(string.Format("Success and Commited"));
        DBHelper.CommitTransaction();
    }
    catch (Exception ex)
    {
        Console.WriteLine(string.Format("Exception and rollback"));
        DBHelper.RollbackTransaction();
    }

    Console.ReadLine();
}

private static void Transaction2() 
{
    try
    {
        DBHelper.BeginTransaction();
        //update model
        DBHelper.ExecuteNonQuery(CommandType.Text, "UPDATE TRole SET RoleName='Marketer' WHERE ID='R1'");
        //throw new Exception("");

        DbParameter param = DBHelper.CreateInDbParameter("@ID", DbType.String, "R1");
        DbDataReader reader= DBHelper.ExecuteReader(CommandType.Text, "SELECT * FROM TRole WHERE ID=@ID",param);
        while (reader.Read()) 
        {
            Console.WriteLine(reader["RoleName"]);
        }

        reader.Close();

        DBHelper.CommitTransaction();
    }
    catch(Exception ex)
    {
        Console.WriteLine(string.Format("Exception and rollback: {0}", ex.Message));
        DBHelper.RollbackTransaction();
        throw;
    }
}
復制代碼

 

2.2.1

當為嵌套事務時,首次調用BeginTransaction,同樣會創建新的TransConnection對象,深度默認為0,並保存在TransConnectionObj字段上;

第n(n>1)次調用時方法時,僅會累加嵌套的深度,不會開起新的事務。

復制代碼
public static void BeginTransaction()
{
    if (TransConnectionObj == null) 
    {
        DbConnection conn = DBClient.GetDbConnection(ConnectionString);
        OpenConn(conn);
        DbTransaction trans = conn.BeginTransaction();
        TransConnectionObj = new TransConnection();
        TransConnectionObj.DBTransaction = trans;
    }
    else 
    {
        TransConnectionObj.Deeps += 1;
    }
}
復制代碼

 

2.2.2

當CommitTransaction提交事務時,如果深度Deeps>0,那麼表示此次提交的事務是內層事務,計數器減1即可;

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved