剛通過開通寫博客的申請,向博客園的大佬致敬,由於一直以來都在網上搜索大家的思想,也有翻遍整個百度都有的找不到的時候,作為一個網民理應為互聯網貢獻一點東西。 下麵是我工作後受一個師傅的影響對資料庫訪問層的封裝,多年以來一直都在使用,用的特別爽,請看下麵的代碼: 第一步、需要編寫一個通用的用於查詢的數據 ...
剛通過開通寫博客的申請,向博客園的大佬致敬,由於一直以來都在網上搜索大家的思想,也有翻遍整個百度都有的找不到的時候,作為一個網民理應為互聯網貢獻一點東西。
下麵是我工作後受一個師傅的影響對資料庫訪問層的封裝,多年以來一直都在使用,用的特別爽,請看下麵的代碼:
第一步、需要編寫一個通用的用於查詢的資料庫存儲過程,這個存儲過程接受“表名、查詢欄位、排序、頁大小、頁碼”:
CREATE PROCEDURE [dbo].[P_Pagination] @tblName varchar(5000), -- 表名 @strGetFields varchar(1000) = '*', -- 需要返回的列 @strWhere varchar(1500) = '', -- 查詢條件(註意: 不要加 where) @OrderSql varchar(255) = '', -- 排序語句(註意: 不要加 order by) @PageSize int = 0, -- 頁尺寸 @PageIndex int = 1, -- 頁碼 @doCount bit = 0 -- 返回記錄總數,非 0 值則返回 AS BEGIN declare @strSQL varchar(5000) -- 主語句 if @doCount <> 0 begin if @strWhere <> '' set @strSQL = 'select count(*) as Total from ' + @tblName + ' where ' + @strWhere else set @strSQL = 'select count(*) as Total from ' + @tblName + '' end --以上代碼的意思是如果@doCount傳遞過來的不是0,就執行總數統計。以下的所有代碼都是@doCount為0的情況 else begin if @PageSize = 0 --返回所有記錄集 begin if @strWhere <> '' set @strSQL = 'select ' + @strGetFields + ' from ' + @tblName + ' where ' + @strWhere + ' order by ' + @OrderSql else set @strSQL = 'select ' + @strGetFields + ' from ' + @tblName + ' order by ' + @OrderSql end else begin if @PageIndex = 1 begin if @strWhere <> '' set @strSQL = 'select top ' + str(@PageSize) + ' ' + @strGetFields + ' from ' + @tblName + ' where ' + @strWhere + ' order by ' + @OrderSql else set @strSQL = 'select top ' + str(@PageSize) + ' ' + @strGetFields + ' from ' + @tblName + ' order by ' + @OrderSql --如果是第一頁就執行以上代碼,這樣會加快執行速度 end else begin --以下代碼賦予了@strSQL以真正執行的SQL代碼 if @strWhere = '' set @strSQL = 'select top ' + str(@PageSize) + ' tblTmp.* from ' + '(select ROW_NUMBER() OVER(order by ' + @OrderSql + ') AS RowNum,' + @strGetFields + ' from ' + @tblName + ') tblTmp where tblTmp.[RowNum] > ' + '(select max([RowNum]) from ' + '(select top ' + str((@PageIndex - 1) * @PageSize) + ' ROW_NUMBER() OVER(order by ' + @OrderSql + ') AS RowNum from ' + @tblName + ') as tblTmp1)' else set @strSQL = 'select top ' + str(@PageSize) + ' tblTmp.* from ' + '(select ROW_NUMBER() OVER(order by ' + @OrderSql + ') AS RowNum,' + @strGetFields + ' from ' + @tblName + ' where ' + @strWhere + ') tblTmp where tblTmp.[RowNum] > ' + '(select max([RowNum]) from ' + '(select top ' + str((@PageIndex - 1) * @PageSize) + ' ROW_NUMBER() OVER(order by ' + @OrderSql + ') AS RowNum from ' + @tblName + ' where ' + @strWhere + ') as tblTmp1)' end end end exec (@strSQL); END
第二步、封裝資料庫訪問層,該層實現執行存儲過程或SQL語句返回 DataTable、SqlDataReader、受影響行數:
namespace Ant.DAL { /// <summary> /// 存儲過程返回值 /// </summary> public class ProcResultValue { /// <summary> /// @Result 字元串返回值 /// </summary> public string ResultValueStr { get; set; } /// <summary> /// Return 任意類型返回值 /// </summary> public int ReturnValueInt { get; set; } /// <summary> /// 存儲過程異常實體信息返回 /// </summary> public string ReturnValue { get { if (ReturnValueInt <= 0) return ResultValueStr; else return ""; } } } /// <summary> /// 資料庫基礎操作類 /// </summary> public class Database { // 測試用Sql連接字元串 private static string SqlConn_Debug = System.Configuration.ConfigurationManager.ConnectionStrings["ConnDB"].ToString();/// <summary> /// 資料庫基礎操作類 構造函數 /// </summary> public Database() { } /// <summary> /// 獲得資料庫連接數據 /// </summary> /// <returns>資料庫連接信息</returns> protected SqlConnection GetConn() { SqlConnection ConnDB = new SqlConnection(SqlConn_Debug); ConnDB.StateChange += new StateChangeEventHandler(ConnDB_StateChange); ConnDB.Open(); return ConnDB; } /// <summary> /// 資料庫鏈接狀態改變事件 /// </summary> protected void ConnDB_StateChange(object sender, StateChangeEventArgs e) { if (e.CurrentState == ConnectionState.Closed) { ((SqlConnection)sender).Dispose(); // 釋放資源 GC.Collect(); // 釋放資源 } } /// <summary> /// 獲得對應表序列的新ID /// </summary> /// <param name="TableName">表名</param> /// <param name="TableCol">表ID列名</param> /// <param name="TableWhere">查詢條件(註意:不添加'where')</param> /// <returns>返回:序列的新ID</returns> protected int GetSequence(string TableName, string TableCol, string tableWhere = "") { DataParameters DP = new DataParameters(); DP.Add("@TableName", SqlDbType.VarChar, TableName); DP.Add("@TableCol", SqlDbType.VarChar, TableCol); DP.Add("@tableWhere", SqlDbType.VarChar, tableWhere); return ExeProc("P_Sequence", DP, false).ReturnValueInt; } /// <summary> /// 通過存儲過程,獲得數據集 DataReader /// </summary> /// <param name="tblName">要查詢的表名</param> /// <param name="strGetFields">要查詢的欄位</param> /// <param name="strWhere">查詢條件(註意:不要加 "where")</param> /// <param name="OrderSql">排序規則(註意:不要加 "order by",且不能為空)</param> /// <param name="PageSize">頁大小 為0時,則不分頁</param> /// <param name="PageIndex">頁索引</param> /// <returns>返回:記錄集 SqlDataReader</returns> protected SqlDataReader GetDataReader(string tblName, string strGetFields, string strWhere, string OrderSql, int PageSize, int PageIndex) { SqlCommand Cmd = new SqlCommand("P_Pagination", GetConn()); Cmd.CommandType = CommandType.StoredProcedure; Cmd.Parameters.Add("@tblName", SqlDbType.VarChar).Value = tblName; Cmd.Parameters.Add("@strGetFields", SqlDbType.VarChar).Value = strGetFields; Cmd.Parameters.Add("@strWhere", SqlDbType.VarChar).Value = strWhere; Cmd.Parameters.Add("@OrderSql", SqlDbType.VarChar).Value = OrderSql; Cmd.Parameters.Add("@PageSize", SqlDbType.Int).Value = PageSize; Cmd.Parameters.Add("@PageIndex", SqlDbType.Int).Value = PageIndex; Cmd.Parameters.Add("@doCount", SqlDbType.Bit).Value = false; return Cmd.ExecuteReader(CommandBehavior.CloseConnection); } /// <summary> /// 通過存儲過程及自定義參數,獲得數據集 DataReader /// </summary> /// <param name="ProcName">存儲過程名</param> /// <param name="DataParas">存儲過程參數集</param> /// <returns>返回:記錄集 SqlDataReader</returns> protected SqlDataReader GetDataReader(string ProcName, DataParameters DataParas) { SqlCommand Cmd = new SqlCommand(ProcName, GetConn()); Cmd.CommandType = CommandType.StoredProcedure; // 遍歷 存儲過程參數集 foreach (System.Collections.DictionaryEntry obj in DataParas.Parameters) { Cmd.Parameters.Add(obj.Key.ToString(), (SqlDbType)((object[])obj.Value)[0]).Value = ((object[])obj.Value)[1]; } return Cmd.ExecuteReader(CommandBehavior.CloseConnection); } /// <summary> /// 通過存儲過程,獲得數據集 DataTable /// </summary> /// <param name="tblName">要查詢的表名</param> /// <param name="strGetFields">要查詢的欄位</param> /// <param name="strWhere">查詢條件(註意:不要加 "where")</param> /// <param name="OrderSql">排序規則(註意:不要加 "order by",且不能為空)</param> /// <param name="PageSize">頁大小 為0時,則不分頁</param> /// <param name="PageIndex">頁索引</param> /// <returns>返回:記錄集 DataTable</returns> protected DataTable GetDataTable(string tblName, string strGetFields, string strWhere, string OrderSql, int PageSize, int PageIndex) { SqlCommand Cmd = new SqlCommand("P_Pagination", GetConn()); Cmd.CommandType = CommandType.StoredProcedure; Cmd.Parameters.Add("@tblName", SqlDbType.VarChar).Value = tblName; Cmd.Parameters.Add("@strGetFields", SqlDbType.VarChar).Value = strGetFields; Cmd.Parameters.Add("@strWhere", SqlDbType.VarChar).Value = strWhere; Cmd.Parameters.Add("@OrderSql", SqlDbType.VarChar).Value = OrderSql; Cmd.Parameters.Add("@PageSize", SqlDbType.Int).Value = PageSize; Cmd.Parameters.Add("@PageIndex", SqlDbType.Int).Value = PageIndex; Cmd.Parameters.Add("@doCount", SqlDbType.Bit).Value = false; SqlDataAdapter DA = new SqlDataAdapter(Cmd); DataTable DT = new DataTable(); DA.Fill(DT); Cmd.Connection.Close(); return DT; } /// <summary> /// 通過指定的存儲過程名稱,獲取數據集 DataTable /// </summary> /// <param name="ProcName">存儲過程名</param> /// <param name="DataParas">存儲過程參數集</param> /// <returns>返回:記錄集 DataTable</returns> protected DataTable GetDataTable(string ProcName, DataParameters DataParas = null) { SqlCommand Cmd = new SqlCommand(ProcName, GetConn()); Cmd.CommandType = CommandType.StoredProcedure; // 遍歷 存儲過程參數集 if(DataParas != null) { foreach (System.Collections.DictionaryEntry obj in DataParas.Parameters) { Cmd.Parameters.Add(obj.Key.ToString(), (SqlDbType)((object[])obj.Value)[0]).Value = ((object[])obj.Value)[1]; } } SqlDataAdapter DA = new SqlDataAdapter(Cmd); DataTable DT = new DataTable(); DA.Fill(DT); Cmd.Connection.Close(); return DT; } /// <summary> /// 執行SQL查詢語句,獲取數據集 DataReader /// </summary> /// <param name="sqlTxt">要執行的SQL語句</param> /// <returns>返回:記錄集 DataReader</returns> protected SqlDataReader GetDataReader(string sqlTxt) { SqlCommand Cmd = new SqlCommand(sqlTxt, GetConn()); Cmd.CommandType = CommandType.Text; return Cmd.ExecuteReader(CommandBehavior.CloseConnection); } /// <summary> /// 執行SQL查詢語句,獲取數據集 DataTable /// </summary> /// <param name="sqlTxt">要執行的SQL語句</param> /// <returns>返回:記錄集 DataTable</returns> protected DataTable GetDataTable(string sqlTxt) { SqlCommand Cmd = new SqlCommand(sqlTxt, GetConn()); Cmd.CommandType = CommandType.Text; SqlDataAdapter DA = new SqlDataAdapter(Cmd); DataTable DT = new DataTable(); DA.Fill(DT); Cmd.Connection.Close(); return DT; } /// <summary> /// 通過存儲過程,獲得數據集 總數 /// </summary> /// <param name="tblName">要查詢的表名</param> /// <param name="strWhere">查詢條件</param> /// <returns>返回:記錄集數量</returns> protected int GetDataCount(string tblName, string strWhere = "") { SqlCommand Cmd = new SqlCommand("P_Pagination", GetConn()); Cmd.CommandType = CommandType.StoredProcedure; Cmd.Parameters.Add("@tblName", SqlDbType.VarChar).Value = tblName; Cmd.Parameters.Add("@strGetFields", SqlDbType.VarChar).Value = "*"; Cmd.Parameters.Add("@strWhere", SqlDbType.VarChar).Value = strWhere; Cmd.Parameters.Add("@OrderSql", SqlDbType.VarChar).Value = ""; Cmd.Parameters.Add("@PageSize", SqlDbType.Int).Value = 0; Cmd.Parameters.Add("@PageIndex", SqlDbType.Int).Value = 1; Cmd.Parameters.Add("@doCount", SqlDbType.Bit).Value = true; int Result = (int)Cmd.ExecuteScalar(); Cmd.Connection.Close(); return Result; } /// <summary> /// 執行SQL查詢語句,並返回數據集長度 /// </summary> /// <param name="sqlTxt">要執行的SQL語句</param> /// <returns>返回:數據集長度</returns> protected int GetDataCount(string sqlTxt) { SqlCommand Cmd = new SqlCommand(sqlTxt, GetConn()); Cmd.CommandType = CommandType.Text; SqlDataAdapter DA = new SqlDataAdapter(Cmd); DataTable DT = new DataTable(); DA.Fill(DT); Cmd.Connection.Close(); return DT.Rows.Count; } /// <summary> /// 執行查詢語句,並返回第一行第一列數據 /// </summary> /// <param name="SelectTxt">要執行的查詢語句</param> /// <returns>返回查詢結果集的第一行第一列數據</returns> protected object GetOnlyData(string SelectTxt) { SqlCommand Cmd = new SqlCommand(SelectTxt, GetConn()); object Result = Cmd.ExecuteScalar(); Cmd.Connection.Close(); return Result; } /// <summary> /// 執行語句,並返回受影響的行數 /// </summary> /// <param name="CmdTxt">要執行的 增、刪、改 語句</param> /// <returns>返回受影響的行數</returns> protected int RunSqlCommand(string CmdTxt) { SqlCommand Cmd = new SqlCommand(CmdTxt, GetConn()); int ExecuteCount = Cmd.ExecuteNonQuery(); Cmd.Connection.Close(); Cmd.Dispose(); return ExecuteCount; } /// <summary> /// 執行存儲過程,並返回存儲過程執行結果(字元串) /// </summary> /// <param name="ProcName">存儲過程名稱</param> /// <param name="DataParas">存儲過程參數集</param> /// <param name="HasResult">該存儲過程是否有返回值</param> /// <returns>存儲過程返回值</returns> protected ProcResultValue ExeProc(string ProcName, DataParameters DataParas, bool HasResult) { // 此處預留異常處理Try catch, 由Application獲取並跳轉異常頁面。 // 返回值 ProcResultValue Result = new ProcResultValue(); // 創建 Command SqlCommand Cmd = new SqlCommand(ProcName, GetConn()); Cmd.CommandType = CommandType.StoredProcedure; // 遍歷 存儲過程參數集 foreach (System.Collections.DictionaryEntry obj in DataParas.Parameters) { Cmd.Parameters.Add(obj.Key.ToString(), (SqlDbType)((object[])obj.Value)[0]).Value = ((object[])obj.Value)[1]; } // 創建返回參數 if (HasResult) { Cmd.Parameters.Add("@Result", SqlDbType.NVarChar, -1); Cmd.Parameters["@Result"].Direction = ParameterDirection.Output; } //存儲過程預設返回值 存儲過程:Return Cmd.Parameters.Add("@Return", SqlDbType.Int); Cmd.Parameters["@Return"].Direction = ParameterDirection.ReturnValue; // 執行存儲過程 Cmd.ExecuteNonQuery(); // 獲得返回值 if (HasResult) Result.ResultValueStr = Cmd.Parameters["@Result"].Value.ToString(); Result.ReturnValueInt = (Cmd.Parameters["@Return"].Value is int ? (int)Cmd.Parameters["@Return"].Value : -1); // 關閉資料庫鏈接 Cmd.Connection.Close(); // 在這裡執行一些存儲過程catch異常的操作 if(Result.ReturnValueInt == -1) { } // 返回執行結果 return Result; } /// <summary> /// 執行函數,並返回函數執行結果 /// </summary> /// <param name="FuncName">函數名稱</param> /// <param name="DataParas">函數參數集</param> /// <param name="ResultType">返回值類型</param> /// <returns>存儲過程返回值</returns> protected object ExeFunc(string FuncName, DataParameters DataParas, SqlDbType ResultType) { // 返回值 object Result = null; // 創建 Command SqlCommand Cmd = new SqlCommand(FuncName, GetConn()); Cmd.CommandType = CommandType.StoredProcedure; // 遍歷 存儲過程參數集 foreach (System.Collections.DictionaryEntry obj in DataParas.Parameters) { Cmd.Parameters.Add(obj.Key.ToString(), (SqlDbType)((object[])obj.Value)[0]).Value = ((object[])obj.Value)[1]; } // 創建返回參數 Cmd.Parameters.Add("@Return", ResultType, -1); Cmd.Parameters["@Return"].Direction = ParameterDirection.ReturnValue; // 執行存儲過程 Cmd.ExecuteScalar(); // 獲得返回值 Result = Cmd.Parameters["@Return"].Value; // 關閉資料庫鏈接 Cmd.Connection.Close(); // 返回執行結果 return Result; } } }
第三步、上面對資料庫訪問封裝方法有一個DataParameters傳參對象,你沒有想錯,這個對象是自己封裝的類,調用起來更加方便,請看下麵代碼
namespace Ant.DAL { /// <summary> /// 資料庫[存儲過程、函數]參數類 /// </summary> public class DataParameters { private Hashtable HT = new Hashtable(); // 存儲過程參數表 /// <summary> /// 資料庫[存儲過程、函數]參數類 構造函數 /// </summary> public DataParameters() { } ///