微軟 SqlHelper代碼、功能、用法介紹:高效的組件

 SqlHelper代碼、功能、用法介紹

數據訪問組件SqlHelper

數據訪問組件是一組通用的訪問數據庫的代碼,在所有項目中都可以用,一般不需要修改。本節使用的是Microsoft提供的數據訪問助手,其封裝很嚴密,且應用簡單。

首先要先添加一個類,並命名爲SqlHelper,系統會提示是否將類放在App_Code文件夾中。此時一定要選擇“是”,因爲放在此文件夾下,系統會自動進行編譯,程序員就可以直接使用,無需另外編譯了。

SqlHelper的功能

SqlHelper的目的是從數據庫獲得信息或將信息保存到數據庫。本實例的SqlHelper主要功能如下。

(1)執行不返回數據的T-Sql命令。例如修改會員卡信息、添加會員資料等。

(2)返回一個字段的T-Sql命令。例如獲取會員卡類型的積分規則。

(3)返回一組數據。例如獲取會員資料、獲取所有會員卡類型等。

(4)緩存參數列表。在執行一條語句時,可能有多個參數,爲了提高速度,將參數緩存。

(5)讀取緩存的參數。

下面用圖表的方式描述SqlHelper類的功能,如圖7-16所示。

圖7-16 SqlHelper功能圖

代碼清單

在SqlHelper類中添加數據庫處理,代碼如清單7-4所示。

代碼清單 SqlHelper代碼

//編號1

using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Collections;

using System.Data.SqlClient;

//編號2

/// <summary>

/// 數據庫的通用訪問代碼

/// 此類爲抽象類,不允許實例化,在應用時直接調用即可

/// </summary>

public abstract class SqlHelper

{

    //獲取數據庫連接字符串,其屬於靜態變量且只讀,項目中所有文檔可以直接使用,但不能修改

    //編號13

    public static readonly string ConnectionStringLocalTransaction =

    ConfigurationManager.ConnectionStrings["connstring"].ConnectionString;

    // 哈希表用來存儲緩存的參數信息,哈希表可以存儲任意類型的參數

    //編號8

    private static Hashtable parmCache = Hashtable.Synchronized(new

    Hashtable());//編號9

    /// <summary>

    ///執行一個不需要返回值的SqlCommand命令,通過指定專用的連接字符串。

    /// 使用參數數組形式提供參數列表

    /// </summary>

    /// <remarks>

    /// 使用示例:

    /// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure,
         /// "PublishOrders", new SqlParameter("@prodid", 24));

    /// </remarks>

    /// <param name="connectionString">一個有效的數據庫連接字符串</param>

    /// <param name="commandType">SqlCommand命令類型 (存儲過程, T-SQL語句, 等等。)

    /// </param>

    /// <param name="commandText">存儲過程的名字或者 T-SQL 語句</param>

    /// <param name="commandParameters">以數組形式提供SqlCommand命令中用到的參數列表

    /// </param>

    /// <returns>返回一個數值表示此SqlCommand命令執行後影響的行數</returns>

    //編號3

    public static int ExecuteNonQuery(string connectionString, CommandType cmdType,

    string cmdText, params SqlParameter[] commandParameters)

    {

        SqlCommand cmd = new SqlCommand();

        //編號4

        using (SqlConnection conn = new SqlConnection(connectionString))

        {

            //通過PrePareCommand方法將參數逐個加入到SqlCommand的參數集合中

            PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);

            int val = cmd.ExecuteNonQuery();

            //清空SqlCommand中的參數列表

            cmd.Parameters.Clear();

            //編號14

            return val;

        }

    }

   

    /// <summary>

    ///執行一條不返回結果的SqlCommand,通過一個已經存在的數據庫連接

    /// 使用參數數組提供參數

    /// </summary>

    /// <remarks>

    /// 使用示例:

    /// int result = ExecuteNonQuery(conn, CommandType.StoredProcedure,

    /// "PublishOrders", new SqlParameter("@prodid", 24));

    /// </remarks>

    /// <param name="conn">一個現有的數據庫連接</param>

    /// <param name="commandType">SqlCommand命令類型 (存儲過程, T-SQL語句, 等等。)

    /// </param>

    /// <param name="commandText">存儲過程的名字或者 T-SQL 語句</param>

    /// <param name="commandParameters">以數組形式提供SqlCommand命令中用到的參數列表

    /// </param>

    /// <returns>返回一個數值表示此SqlCommand命令執行後影響的行數</returns>

    //編號5

    public static int ExecuteNonQuery(SqlConnection connection, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)

    {

        SqlCommand cmd = new SqlCommand();

        PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);

        int val = cmd.ExecuteNonQuery();

        cmd.Parameters.Clear();

        return val;

    }

    /// <summary>

    /// 執行一條不返回結果的SqlCommand,通過一個已經存在的數據庫事物處理

    /// 使用參數數組提供參數

    /// </summary>

    /// <remarks>

    /// 使用示例:

    /// int result = ExecuteNonQuery(trans, CommandType.StoredProcedure,

    /// "PublishOrders", new SqlParameter("@prodid", 24));

    /// </remarks>

    /// <param name="trans">一個存在的 sql 事物處理</param>

    /// <param name="commandType">SqlCommand命令類型 (存儲過程, T-SQL語句, 等等。)

    /// </param>

    /// <param name="commandText">存儲過程的名字或者 T-SQL 語句</param>

    /// <param name="commandParameters">以數組形式提供SqlCommand命令中用到的參數列表

    /// </param>

    /// <returns>返回一個數值表示此SqlCommand命令執行後影響的行數</returns>

    //編號12

    public static int ExecuteNonQuery(SqlTransaction trans, CommandType cmdType,

string cmdText, params SqlParameter[] commandParameters)

    {

       SqlCommand cmd = new SqlCommand();

        PrepareCommand(cmd, trans.Connection, trans, cmdType, cmdText, commandParameters);

        int val = cmd.ExecuteNonQuery();

        cmd.Parameters.Clear();

        return val;

    }

    /// <summary>

    /// 執行一條返回結果集的SqlCommand命令,通過專用的連接字符串。

    /// 使用參數數組提供參數

    /// </summary>

    /// <remarks>

    /// 使用示例:

    /// SqlDataReader r = ExecuteReader(connString, CommandType.StoredProcedure,

    /// "PublishOrders", new SqlParameter("@prodid", 24));

    /// </remarks>

    /// <param name="connectionString">一個有效的數據庫連接字符串</param>

    /// <param name="commandType">SqlCommand命令類型 (存儲過程, T-SQL語句, 等等。)

    /// </param>

    /// <param name="commandText">存儲過程的名字或者 T-SQL 語句</param>

    /// <param name="commandParameters">以數組形式提供SqlCommand命令中用到的參數列表

    /// </param>

    /// <returns>返回一個包含結果的SqlDataReader</returns>

    public static SqlDataReader ExecuteReader(string connectionString, CommandType

cmdType, string cmdText, params SqlParameter[] commandParameters)

    {

       SqlCommand cmd = new SqlCommand();

        SqlConnection conn = new SqlConnection(connectionString);

        // 在這裏使用try/catch處理是因爲如果方法出現異常,則SqlDataReader就不存在,

        //CommandBehavior.CloseConnection的語句就不會執行,觸發的異常由catch捕獲。

        //關閉數據庫連接,並通過throw再次引發捕捉到的異常。

      try

        {

            PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);

            SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);

            cmd.Parameters.Clear();

            return rdr;

        }

        catch

        {

            conn.Close();

            throw; //編號7

        }

    }

    /// <summary>

    /// 執行一條返回第一條記錄第一列的SqlCommand命令,通過專用的連接字符串。

    /// 使用參數數組提供參數

    /// </summary>

    /// <remarks>

    /// 使用示例:

    /// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure,

    /// "PublishOrders", new SqlParameter("@prodid", 24));

    /// </remarks>

    /// <param name="connectionString">一個有效的數據庫連接字符串</param>

    /// <param name="commandType">SqlCommand命令類型 (存儲過程, T-SQL語句, 等等。)

    /// </param>

    /// <param name="commandText">存儲過程的名字或者 T-SQL 語句</param>

    /// <param name="commandParameters">以數組形式提供SqlCommand命令中用到的參數列表

    /// </param>

    /// <returns>返回一個object類型的數據,可以通過 Convert.To{Type}方法轉換類型</returns>

    public static object ExecuteScalar(string connectionString, CommandType

cmdType, string cmdText, params SqlParameter[] commandParameters)

    {

        SqlCommand cmd = new SqlCommand();

        using (SqlConnection connection = new SqlConnection(connectionString))

        {

            PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);

            object val = cmd.ExecuteScalar();

            cmd.Parameters.Clear();

            return val;

        }

    }

    /// <summary>

    /// 執行一條返回第一條記錄第一列的SqlCommand命令,通過已經存在的數據庫連接。

    /// 使用參數數組提供參數

    /// </summary>

    /// <remarks>

    /// 使用示例:

    /// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure,

    /// "PublishOrders", new SqlParameter("@prodid", 24));

    /// </remarks>

    /// <param name="conn">一個已經存在的數據庫連接</param>

    /// <param name="commandType">SqlCommand命令類型 (存儲過程, T-SQL語句, 等等。)

    /// </param>

    /// <param name="commandText">存儲過程的名字或者 T-SQL 語句</param>

    /// <param name="commandParameters">以數組形式提供SqlCommand命令中用到的參數列表

    /// </param>

    /// <returns>返回一個object類型的數據,可以通過 Convert.To{Type}方法轉換類型

    /// </returns>

    public static object ExecuteScalar(SqlConnection connection, CommandType

cmdType, string cmdText, params SqlParameter[] commandParameters)

    {

        SqlCommand cmd = new SqlCommand();

        PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);

        object val = cmd.ExecuteScalar();

        cmd.Parameters.Clear();

        return val;

    }

    /// <summary>

    /// 緩存參數數組

    /// </summary>

    /// <param name="cacheKey">參數緩存的鍵值</param>

    /// <param name="cmdParms">被緩存的參數列表</param>

    public static void CacheParameters(string cacheKey, params SqlParameter[]

commandParameters)

    {

    //編號10

        parmCache[cacheKey] = commandParameters;

    }

    /// <summary>

    /// 獲取被緩存的參數

    /// </summary>

    /// <param name="cacheKey">用於查找參數的KEY值</param>

    /// <returns>返回緩存的參數數組</returns>

    public static SqlParameter[] GetCachedParameters(string cacheKey)

    {

       SqlParameter[] cachedParms = (SqlParameter[])parmCache[cacheKey];

        if (cachedParms == null)

            return null;

        //新建一個參數的克隆列表

        SqlParameter[] clonedParms = new SqlParameter[cachedParms.Length];

        //通過循環爲克隆參數列表賦值

        for (int i = 0, j = cachedParms.Length; i < j; i++)

            //使用clone方法複製參數列表中的參數

            //編號11

            clonedParms[i] = (SqlParameter)((ICloneable)cachedParms[i]).Clone();

        return clonedParms;

    }

    /// <summary>

    /// 爲執行命令準備參數

    /// </summary>

    /// <param name="cmd">SqlCommand 命令</param>

    /// <param name="conn">已經存在的數據庫連接</param>

    /// <param name="trans">數據庫事物處理</param>

    /// <param name="cmdType">SqlCommand命令類型 (存儲過程,T-SQL語句,等等。) </param>

    /// <param name="cmdText">Command text,T-SQL語句 例如 Select * from

    /// Products</param>

    /// <param name="cmdParms">返回帶參數的命令</param>

    //編號6

    private static void PrepareCommand(SqlCommand cmd, SqlConnection conn,

SqlTransaction trans, CommandType cmdType, string cmdText, SqlParameter[]
         cmdParms)

    {

        //判斷數據庫連接狀態

        if (conn.State != ConnectionState.Open)

            conn.Open();

        cmd.Connection = conn;

        cmd.CommandText = cmdText;

        //判斷是否需要事物處理

        if (trans != null)

            cmd.Transaction = trans;

        cmd.CommandType = cmdType;

        if (cmdParms != null)

        {

            foreach (SqlParameter parm in cmdParms)

                cmd.Parameters.Add(parm);

        }

    }

}

代碼技術分析

代碼清單7-4是一個比較完整的數據訪問組件,下面分析這些代碼的具體實現。

(1)Using關鍵字:見代碼編號1。Using處理對命名空間的引用。通常,如果系統提示找不到某個類,一定要仔細檢查是否引用了這個類的命名空間。在C# 2.0中Using還可以實現命名空間的別名,例如:Using sc =System.Collections。別名就是用來簡化命名空間的,別名的使用語句是:sc::ArrayList list=new sc::Arraylist( )。

(2)註釋:見代碼編號2。在方法上面一行如果輸入“///”,系統會自動將此方法的註釋架構搭建好,主要包括Summary和param name。如果方法有返回值,還包括returns;如果需要特殊說明可以使用remarks標誌。根據這個結構,可以很容易地描述清楚整個方法的組成及使用方法。在註釋中使用“///”,將來在代碼調用時,會出現提示,提示的內容就是所添加的註釋。

(3)CommandType的使用:見代碼編號3。SQL Server數據處理的兩種方法:存儲過程和T-SQL語句。每條執行語句都有個參數CommandType,這是個枚舉類型,有3個選項:StoredProcedure、TableDirect和Text。它們分別表示存儲過程、表和T-SQL語句。如果CommandType參數選擇StoredProcedure,則cmdText參數就是存儲過程的名字;如果CommandType是Text,則cmdText是SQL語句;如果CommandType是TableDirect,則cmdText是表名稱。

(4)Using語句:見代碼編號4。在Using語句中,用“{}”定義一個範圍,在語句完成時釋放語句內使用的資源。Using語句通常用在獲取數據的方法中,語句的範圍是從打開數據庫連接開始,到所有使用連接的資源都運行完畢後終止。Using語句可以與多個對象一起使用。使用Using語句的對象必須繼承IDispose接口。此接口實現了Dispose方法,該方法纔是釋放對象資源的執行者。

(5)參數數組:見代碼編號5。在C#中不允許使用可選參數,所以參數通常由不指定大小的數組來實現。數組中參數的添加由PrepareCommand方法完成。

(6)SQL事務處理:見代碼編號6。事務是指一組相關聯的操作。在事務處理時,通常鎖住相關的表,等事務處理完成後才解鎖,這樣保證了數據的完整性。事務一般包括3個方法:開始事務、執行事務和事務回滾(RollBack)。如果事務中的一條語句出現問題,則事務回滾,其他語句的執行也被取消。

(7)throw:見代碼編號7。再次引發捕獲的異常,目的是向文本中添加異常處理信息。如果要引發異常,throw和catch一定要搭配使用,如果catch有參數,則throw也要帶參數,相反亦然。

(8)哈希表:見代碼編號8。表示鍵/值(key/value)對的組合。通過鍵值的映射來訪問哈希代碼。.NET中的哈希表是System.Collections命名空間提供的一個容器,英文名稱爲HashTable,通過key來實現快速查找,key區分大小寫。value存儲key對應的值,通常表現爲object類型,當取值時要進行相應的類型轉換。

(9)哈希表的同步包裝:見代碼編號9。private static Hashtable parmCache = Hashtable. Synchronized(new Hashtable( ))這條語句實現了哈希表的同步包裝,包裝是基於線程安全的。此處的哈希表是static類型的靜態變量,既然是static,就是一次定義,全局使用。所有的參數都使用這個哈希表,那如何保證其他人在修改的時候不影響自己的讀取呢?以前可以使用lock的方法先鎖定表,不允許他人修改,讀取完畢後再解鎖。現在.NET提供了HashTable的Synchronized方法,實現同樣的功能,不需要手動加鎖,直接由系統框架完成。

(10)緩存參數列表:見代碼編號10。緩存參數列表就是將參數信息保存在已經定義的靜態HashTable中。因爲HashTable是靜態的,一旦定義,就分配了內存地址,在項目中隨時都可以使用,起到了緩存數據的作用。

(11)clone:克隆。見代碼編號11。在.NET中,幾乎所有繼承Collections類的集合都具有clone的方法。在獲取緩存參數的方法中有下面這句代碼:clonedParms[i] = (SqlParameter) ((ICloneable)cachedParms[i]).Clone( )。因爲所有的參數都保存在一個HashTable中,表中保存的只是參數的名字,而參數的內容則是由不同的調用給予不同的值。爲了正確反映調用者的值,必須克隆出一個參數列表,由調用者根據功能賦予對應的值。

(12)方法重載:見代碼編號12。定義了兩個或多個具有相同名稱但參數不同的方法。在SqlHelper中,ExcuteNonQuery被重載了4次,通過代碼中的註釋可以很清楚地看出參數列表的不同。在實際應用中,根據功能環境調用相應的方法。

(13)ConfigurationManager:見代碼編號13。是ASP.NET 2.0中新加的一個類,主要對Web.config文件進行管理。可以輕鬆獲取在Web.config文件中定義的配置,通常用來獲取數據庫連接字符串和個性化配置信息。本例在Web.config中添加了下面這行數據庫連接字符串配置。

<connectionStrings >

<add name="connstring" connectionString ="server=.;database=membercard; uid=sa; pwd="/>

</connectionStrings>

(14)ExcuteNonQuery方法的返回值:見代碼編號14。在SqlCommand的方法中,ExcuteNonQuery用來執行插入、更新或刪除等操作。程序並不要求有任何返回值,但在SqlHelper中定義此方法時返回了一個數值型數據。該數據用來表示執行當前語句後數據庫中被影響的行數。雖然在此定義了返回值,但在程序的調用中,可以不用返回值,直接執行方法。例如:SqlHelper. ExcuteNonQuery( )就是正確的,不一定非要寫成 int val= SqlHelper. ExcuteNonQuery( )。如果程序中需要的不是int值,還可以進行轉換。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章