日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

微軟提供的數(shù)據(jù)訪問組件SqlHelper

 Frank_Chia 2009-10-10

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

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

  SqlHelper的目的是從數(shù)據(jù)庫獲得信息或?qū)⑿畔⒈4娴綌?shù)據(jù)庫。本實例的SqlHelper主要功能如下。

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

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

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

 ?。?)緩存參數(shù)列表。在執(zhí)行一條語句時,可能有多個參數(shù),為了提高速度,將參數(shù)緩存。

 ?。?)讀取緩存的參數(shù)。

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

微軟提供的數(shù)據(jù)訪問組件SqlHelper

  在SqlHelper類中添加數(shù)據(jù)庫處理,代碼如下:

  

      一、原程序://編號1using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Collections;
using System.Data.SqlClient;
//編號2
/**//// <summary>
/// 數(shù)據(jù)庫的通用訪問代碼
/// 此類為抽象類,不允許實例化,在應(yīng)用時直接調(diào)用即可
/// </summary>
public abstract class SqlHelper
...{
    //獲取數(shù)據(jù)庫連接字符串,其屬于靜態(tài)變量且只讀,項目中所有文檔可以直接使用,但不能修改
    
//編號13
    public static readonly string ConnectionStringLocalTransaction =
    ConfigurationManager.ConnectionStrings["connstring"].ConnectionString;
    // 哈希表用來存儲緩存的參數(shù)信息,哈希表可以存儲任意類型的參數(shù)
   
 //編號8
    private static Hashtable parmCache = Hashtable.Synchronized(new Hashtable());
//編號9

    /**//// <summary>
    ///執(zhí)行一個不需要返回值的SqlCommand命令,通過指定專用的連接字符串。
    /// 使用參數(shù)數(shù)組形式提供參數(shù)列表 
    /// </summary>
    /// <remarks>
    /// 使用示例:
    ///  int result = ExecuteNonQuery(connString, CommandType.StoredProcedure,
    ///  "PublishOrders", new SqlParameter("@prodid", 24));
    /// </remarks>
    /// <param name="connectionString">一個有效的數(shù)據(jù)庫連接字符串</param>
    /// <param name="commandType">SqlCommand命令類型 (存儲過程, T-SQL語句, 等等。) 
    /// </param>
    /// <param name="commandText">存儲過程的名字或者 T-SQL 語句</param>
    /// <param name="commandParameters">以數(shù)組形式提供SqlCommand命令中用到的參數(shù)列表
    /// </param>
    /// <returns>返回一個數(shù)值表示此SqlCommand命令執(zhí)行后影響的行數(shù)</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方法將參數(shù)逐個加入到SqlCommand的參數(shù)集合中
            PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
            int val = cmd.ExecuteNonQuery();
            //清空SqlCommand中的參數(shù)列表
            cmd.Parameters.Clear();
 //編號14
            return val;
        }
    }

 

    /**//// <summary>
    ///執(zhí)行一條不返回結(jié)果的SqlCommand,通過一個已經(jīng)存在的數(shù)據(jù)庫連接 
    /// 使用參數(shù)數(shù)組提供參數(shù)
    /// </summary>
    /// <remarks>
    /// 使用示例:  
    /// int result = ExecuteNonQuery(conn, CommandType.StoredProcedure, 
    /// "PublishOrders", new SqlParameter("@prodid", 24));
    /// </remarks>
    /// <param name="conn">一個現(xiàn)有的數(shù)據(jù)庫連接</param>
    /// <param name="commandType">SqlCommand命令類型 (存儲過程, T-SQL語句, 等等。) 
    /// </param>
    /// <param name="commandText">存儲過程的名字或者 T-SQL 語句</param>
    /// <param name="commandParameters">以數(shù)組形式提供SqlCommand命令中用到的參數(shù)列表
    /// </param>
    /// <returns>返回一個數(shù)值表示此SqlCommand命令執(zhí)行后影響的行數(shù)</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>
    /// 執(zhí)行一條不返回結(jié)果的SqlCommand,通過一個已經(jīng)存在的數(shù)據(jù)庫事物處理 
    /// 使用參數(shù)數(shù)組提供參數(shù)
    /// </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">以數(shù)組形式提供SqlCommand命令中用到的參數(shù)列表
    /// </param>
    /// <returns>返回一個數(shù)值表示此SqlCommand命令執(zhí)行后影響的行數(shù)</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>
    /// 執(zhí)行一條返回結(jié)果集的SqlCommand命令,通過專用的連接字符串。
    /// 使用參數(shù)數(shù)組提供參數(shù)
    /// </summary>
    /// <remarks>
    /// 使用示例:  
    ///  SqlDataReader r = ExecuteReader(connString, CommandType.StoredProcedure, 
    /// "PublishOrders", new SqlParameter("@prodid", 24));
    /// </remarks>
    /// <param name="connectionString">一個有效的數(shù)據(jù)庫連接字符串</param>
    /// <param name="commandType">SqlCommand命令類型 (存儲過程, T-SQL語句, 等等。) 
    /// </param>
    /// <param name="commandText">存儲過程的名字或者 T-SQL 語句</param>
    /// <param name="commandParameters">以數(shù)組形式提供SqlCommand命令中用到的參數(shù)列表
    /// </param>
    /// <returns>返回一個包含結(jié)果的SqlDataReader</returns>

    public static SqlDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
    ...{

 //編號7
        SqlCommand cmd = new SqlCommand();
        SqlConnection conn = new SqlConnection(connectionString);
        // 在這里使用try/catch處理是因為如果方法出現(xiàn)異常,則SqlDataReader就不存在,
        //CommandBehavior.CloseConnection的語句就不會執(zhí)行,觸發(fā)的異常由catch捕獲。
        //關(guān)閉數(shù)據(jù)庫連接,并通過throw再次引發(fā)捕捉到的異常?!?nbsp;
        try
        ...{
            PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
            SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
            cmd.Parameters.Clear();
            return rdr;
        }
        catch
        ...{
            conn.Close();
            throw; 
        }
    }

    /**//// <summary>
    /// 執(zhí)行一條返回第一條記錄第一列的SqlCommand命令,通過專用的連接字符串。 
    /// 使用參數(shù)數(shù)組提供參數(shù)
    /// </summary>
    /// <remarks>
    /// 使用示例:  
    ///  Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, 
    /// "PublishOrders", new SqlParameter("@prodid", 24));
    /// </remarks>
    /// <param name="connectionString">一個有效的數(shù)據(jù)庫連接字符串</param>
    /// <param name="commandType">SqlCommand命令類型 (存儲過程, T-SQL語句, 等等。) 
    /// </param>
    /// <param name="commandText">存儲過程的名字或者 T-SQL 語句</param>
    /// <param name="commandParameters">以數(shù)組形式提供SqlCommand命令中用到的參數(shù)列表
    /// </param>
    /// <returns>返回一個object類型的數(shù)據(jù),可以通過 Convert.To{Type}方法轉(zhuǎn)換類型</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>
    /// 執(zhí)行一條返回第一條記錄第一列的SqlCommand命令,通過已經(jīng)存在的數(shù)據(jù)庫連接。
    /// 使用參數(shù)數(shù)組提供參數(shù)
    /// </summary>
    /// <remarks>
    /// 使用示例: 
    ///  Object obj = ExecuteScalar(connString, CommandType.StoredProcedure,
    /// "PublishOrders", new SqlParameter("@prodid", 24));
    /// </remarks>
    /// <param name="conn">一個已經(jīng)存在的數(shù)據(jù)庫連接</param>
    /// <param name="commandType">SqlCommand命令類型 (存儲過程, T-SQL語句, 等等。) 
    /// </param>
    /// <param name="commandText">存儲過程的名字或者 T-SQL 語句</param>
    /// <param name="commandParameters">以數(shù)組形式提供SqlCommand命令中用到的參數(shù)列表
    /// </param>
    /// <returns>返回一個object類型的數(shù)據(jù),可以通過 Convert.To{Type}方法轉(zhuǎn)換類型
    /// </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>
    /// 緩存參數(shù)數(shù)組
    /// </summary>
    /// <param name="cacheKey">參數(shù)緩存的鍵值</param>
    /// <param name="cmdParms">被緩存的參數(shù)列表</param>

    public static void CacheParameters(string cacheKey, params SqlParameter[] commandParameters)
    ...{

       
 //編號10
        parmCache[cacheKey] = commandParameters;

    }

    /**//// <summary>
    /// 獲取被緩存的參數(shù)
    /// </summary>
    /// <param name="cacheKey">用于查找參數(shù)的KEY值</param>
    /// <returns>返回緩存的參數(shù)數(shù)組</returns>

    public static SqlParameter[] GetCachedParameters(string cacheKey)
    ...{

        SqlParameter[] cachedParms = (SqlParameter[])parmCache[cacheKey];
        if (cachedParms == null)
            return null;
        //新建一個參數(shù)的克隆列表
        SqlParameter[] clonedParms = new SqlParameter[cachedParms.Length];
        //通過循環(huán)為克隆參數(shù)列表賦值
        for (int i = 0, j = cachedParms.Length; i < j; i++)
            //使用clone方法復(fù)制參數(shù)列表中的參數(shù)
 //編號11
            clonedParms[i] = (SqlParameter)((ICloneable)cachedParms[i]).Clone();
        return clonedParms;
    }

    /**//// <summary>
    /// 為執(zhí)行命令準備參數(shù)
    /// </summary>
    /// <param name="cmd">SqlCommand 命令</param>
    /// <param name="conn">已經(jīng)存在的數(shù)據(jù)庫連接</param>
    /// <param name="trans">數(shù)據(jù)庫事物處理</param>
    /// <param name="cmdType">SqlCommand命令類型 (存儲過程,T-SQL語句,等等。) </param>
    /// <param name="cmdText">Command text,T-SQL語句 例如 Select * from 
    /// Products</param>
    /// <param name="cmdParms">返回帶參數(shù)的命令</param>

    
//編號6
    private static void PrepareCommand(SqlCommand cmd, SqlConnection conn,SqlTransaction trans, CommandType cmdType, string cmdText, SqlParameter[]
         cmdParms)
    ...{

        //判斷數(shù)據(jù)庫連接狀態(tài)
        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);

        }
    }

}
     二、代碼分析:
     代碼是一個比較完整的數(shù)據(jù)訪問組件,下面分析這些代碼的具體實現(xiàn)。
  ?。?)Using關(guān)鍵字:見代碼編號1。Using處理對命名空間的引用。通常,如果系統(tǒng)提示找不到某個類,一定要仔細檢查是否引用了這個類的命名空間。在C# 2.0中Using還可以實現(xiàn)命名空間的別名,例如:Using sc =System.Collections。別名就是用來簡化命名空間的,別名的使用語句是:sc::ArrayList list=new sc::Arraylist( )。

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

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

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

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

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

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

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

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

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

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

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

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

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

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


 

 

 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多