程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> c# 輕量級 ORM 框架 之 DBHelper 實現 (三)

c# 輕量級 ORM 框架 之 DBHelper 實現 (三)

編輯:C#入門知識

已經做出來的東西通常感覺有些簡單,一些新手或許聽到"框架"一類的詞覺得有些"高深",簡單來說orm就是把ado的封裝.   在介紹這個框架的第一篇博文,已經把DalBase介紹了一下設計思路,本篇的DBHelper對象也是給dalBase來用的,可以說框架的所有定義對象都是為了它.   這裡起名叫DBHelper,因為我也是從寫SQLHelper開始的,DBHelper只不過是所有類型對ado操作的各種方法的封裝,所以本篇博文希望給c#新手,或是對ado.net認識比較模糊的有一些幫助.   首先DBHelper定義是個抽象的,因為我不知道DalBase 到底要訪問哪種數據庫,但我知道不管哪中數據庫都會有鏈接字符串,那我就要求,必須要有連接字符串.     public DbHelperBase(string connStr)         {             _ConnStr = connStr;         }     DbHelper是個抽象的,那它的成員必然就不能有具體對象.   那就把ado.net常用的對象定義出來.(如果你是初學者,我的建議是 用到哪個對象再去定義,否則到後期自己都不知道定義它干啥呢)   復制代碼         protected abstract DbConnection DBConnectionObj { get; }         protected abstract DbCommand DbCommandObj { get; }         protected abstract DbDataAdapter DbDataAdapterObj { get; }         protected DbTransaction DbTransObj;           public DbConnection CurrentConnection         {             get             {                 return DBConnectionObj;             }         }   復制代碼 說明一下,為什麼事務對象不是抽象的,因為事務對象始終是有DbConnection來創建的,我不用知道它具體是什麼類型.   DbConnection 對象public也是為了擴展其它功能而存在的.   定義了是否事務的變量,所有ado操作都會判斷當前是否處於事務的標記.   bool _IsTrans = false; 初學.net的朋友,應該都會有一個SQLHelper的類,我也曾經看過都大同小異,而且普遍都沒有事務的實現,如果你中槍了,那麼恭喜你,你即將會改變你sqlHelper的實現.   如下代碼:   復制代碼      /// <summary>         /// 執行一條指定命令類型(SQL語句或存儲過程等)的SQL語句,返回所影響行數         /// </summary>         public int ExecNonQuery(string sqlText, CommandType cmdType, params DbParameter[] param)         {             using (SqlConnection conn = new SqlConnection(_ConnStr))             {                 using (SqlCommand cmd = new SqlCommand(sqlText, conn))                 {                     cmd.CommandType = cmdType;                     if (param != null)                         cmd.Parameters.AddRange(param);                     conn.Open();                     return cmd.ExecuteNonQuery();                 }             }         } 復制代碼 以上代碼看起來是沒什麼問題,但如果要啟用事務的話想想是否可以實現呢?   如果說改造一下加上事務的代碼就行的話   如下:    SqlTransaction tran = conn.BeginTransaction();  cmd.Transaction = tran;    這樣顯然是錯的,因為我們往往多條執行語句通常是分多次調用 ExecNonQuery() 方法的.   這樣的一個ado方法的封裝顯然是不合理的.   如果多個增刪改查(注意:查詢也可能在是事務裡)的方法,在一個事務裡,那麼必須是一個數據庫連接(Connection)   這就是為什麼把那三個對象定義到外面的原因之一了,最重要的原因是我需要子類去重寫它.   下面看看我的實現:   復制代碼         /// <summary>         /// 打開連接,如果已經打開則什麼都不執行了         /// </summary>         void OpenConnection()         {             if (DBConnectionObj.State != ConnectionState.Open)             {                 DBConnectionObj.ConnectionString = _ConnStr;                 DBConnectionObj.Open();             }         } 復制代碼 復制代碼           /// <summary>         /// 給當前DbCommand對象賦值,並且OpenConnection();         /// </summary>         void SetCommandAndOpenConnect(string sqlText, CommandType cmdType, params DbParameter[] param)         {             //按說賦值Connection,CommandType,是不用多次賦值的             DbCommandObj.CommandType = cmdType;             DbCommandObj.Connection = DBConnectionObj;             DbCommandObj.Parameters.Clear();             if (param != null)             {                 DbCommandObj.Parameters.AddRange(param);             }             DbCommandObj.CommandText = sqlText;             OpenConnection();         } 復制代碼 復制代碼         /// <summary>         /// 執行一條指定命令類型(SQL語句或存儲過程等)的SQL語句,返回所影響行數         /// </summary>         public int ExecNonQuery(string sqlText, CommandType cmdType, params DbParameter[] param)         {             try             {                 SetCommandAndOpenConnect(sqlText, cmdType, param);                 return DbCommandObj.ExecuteNonQuery();             }             catch (Exception ex)             {                 throw ex;             }             finally             {                 CloseConnect();             }         } 復制代碼 看到這三個方法或許對於初學者會感到迷茫了,沒有看到任何有關事務的代碼呢,兜個圈子,現在想象一下如果加事務的話,需要做什麼?   我們先從理論上認識一下,事務處理的流程   1.指定事務是哪個Connection   2.Command的事務對象指定到該事務.   3.Open()   4.提交或回滾(我是能寫漢字的地方絕不寫拼音)   5.關閉連接.   繼續說這幾個方法,為什麼定義SetCommandAndOpenConnect 和 OpenConnection 這兩個方法,本著盡量減少重復代碼的原則.僅此而已.   既然Connection和Command都已經定義到方法外了,那就是說我只要再執行Command.ExecuteNonQuery()方法前,給他們賦值就行了.   也就是開始事務只需要給這個兩個對象賦值即可   事務的相關代碼如下:   復制代碼         /// <summary>         /// 開始執行事務         /// </summary>         public void TransStart()         {             OpenConnection();             DbTransObj = DBConnectionObj.BeginTransaction();             DbCommandObj.Transaction = DbTransObj;             _IsTrans = true;         }         /// <summary>         /// 事務提交         /// </summary>         public void TransCommit()         {             _IsTrans = false;             DbTransObj.Commit();             CloseConnect();         }         /// <summary>         /// 事務回滾         /// </summary>         public void TransRollback()         {             _IsTrans = false;             DbTransObj.Rollback();             CloseConnect();         } 復制代碼 這就是事務的方法了.   最後一個CloseConnect()方法,差點把它遺忘了   復制代碼         /// <summary>         /// 關閉連接,如果沒有開始事務或連接打開時才關閉         /// </summary>         void CloseConnect()         {             if (!_IsTrans)             {                 if (DBConnectionObj.State == ConnectionState.Open)                 {                     DBConnectionObj.Close();                     DBConnectionObj.Dispose();                 }             }         } 復制代碼 當開始事務時,連接是不能關的.只有提交了或回滾了才會把當前連接斷掉.   到這裡其實DbHelper的設計基本完成,再貼一下關於查詢的幾個方法,和執行類似就不解釋了.   復制代碼      /// <summary>         /// 獲得首行首列         /// </summary>         public object GetScalar(string sqlText, CommandType cmdType, params DbParameter[] param)         {             try             {                 SetCommandAndOpenConnect(sqlText, cmdType, param);                 return DbCommandObj.ExecuteScalar();               }             catch (Exception ex)             {                 throw ex;             }             finally             {                 CloseConnect();             }         }      /// <summary>         /// 執行一條SQL語句返回DataSet對象         /// </summary>         public DataSet GetDataSet(string sqlText, CommandType cmdType, params DbParameter[] param)         {             try             {                 SetCommandAndOpenConnect(sqlText, cmdType, param);                 DbDataAdapterObj.SelectCommand = DbCommandObj;                 DataSet ds = new DataSet();                 DbDataAdapterObj.Fill(ds);                 return ds;             }             catch (Exception ex)             {                 throw ex;             }             finally             {                 CloseConnect();             }         }        /// <summary>         /// 獲得DataReader對象         /// </summary>         public DbDataReader GetDataReader(string sqlText, CommandType cmdType, params DbParameter[] param)         {             try             {                 SetCommandAndOpenConnect(sqlText, cmdType, param);                 CommandBehavior cmdBehavior = CommandBehavior.CloseConnection;                 if (_IsTrans)                 {                     cmdBehavior = CommandBehavior.Default;                 }                 DbDataReader dbReader = DbCommandObj.ExecuteReader(cmdBehavior);                 return dbReader;             }             catch (Exception ex)             {                 throw ex;             }             finally             {                 //DataReader用dbReader對象來關閉                 //CloseConnect();             }         } 復制代碼 這裡需要注意的是關於返回DataReader對象時不能關閉Connect,和 cmdBehavior 的賦值.       好了,到這DBHelper的設計和核心代碼已經全部實現了.   試想一下我現在要完成SQLServerHelper的實現需要做的是什麼?   當然只要實現父類的那幾個抽象屬性就行了.   代碼如下:  public class SQLHelper : DbHelperBase     {         public SQLHelper(string connStr)             : base(connStr)         { }           SqlConnection _DBConnectionObj;         SqlCommand _DbCommandObj;         SqlDataAdapter _DbDataAdapterObj;           protected override DbConnection DBConnectionObj         {             get             {                 //SqlBulkCopy aa = new SqlBulkCopy(new SqlConnection());                 if (_DBConnectionObj == null)                 {                     _DBConnectionObj = new SqlConnection(_ConnStr);                 }                 return _DBConnectionObj;             }         }           protected override DbCommand DbCommandObj         {             get             {                 if (_DbCommandObj == null)                 {                     _DbCommandObj = new SqlCommand();                 }                 return _DbCommandObj;             }         }           protected override DbDataAdapter DbDataAdapterObj         {             get             {                 if (_DbDataAdapterObj == null)                 {                     _DbDataAdapterObj = new SqlDataAdapter();                 }                 return _DbDataAdapterObj;             }         }       } 復制代碼 OracleHelper,oledbhelper,SQLiteHelper,就不貼代碼了.

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