SqlHelper 類實現詳細信息

SqlHelper 類實現詳細信息
SqlHelper 類用於通過一組靜態方法來封裝數據訪問功能。該類不能被繼承或實例化,因此將其聲明爲包含專用構造函數的不可繼承類。
在 SqlHelper 類中實現的每種方法都提供了一組一致的重載。這提供了一種很好的使用 SqlHelper 類來執行命令的模式,同時爲開發人員選擇訪問數據的方式提供了必要的靈活性。每種方法的重載都支持不同的方法參數,因此開發人員可以確定傳遞連接、事務和參數信息的方式。在 SqlHelper 類中實現的方法包括:
ExecuteNonQuery。此方法用於執行不返回任何行或值的命令。這些命令通常用於執行數據庫更新,但也可用於返回存儲過程的輸出參數。
ExecuteReader。此方法用於返回 SqlDataReader 對象,該對象包含由某一命令返回的結果集。
ExecuteDataset。此方法返回 DataSet 對象,該對象包含由某一命令返回的結果集。
ExecuteScalar。此方法返回一個值。該值始終是該命令返回的第一行的第一列。
ExecuteXmlReader。此方法返回 FOR XML 查詢的 XML 片段。
除了這些公共方法外,SqlHelper 類還包含一些專用函數,用於管理參數和準備要執行的命令。不管客戶端調用什麼樣的方法實現,所有命令都通過 SqlCommand 對象來執行。在 SqlCommand 對象能夠被執行之前,所有參數都必須添加到 Parameters 集合中,並且必須正確設置 Connection、CommandType、CommandText 和 Transaction 屬性。SqlHelper 類中的專用函數主要用於提供一種一致的方式,以便向 SQL Server 數據庫發出命令,而不考慮客戶端應用程序調用的重載方法實現。SqlHelper 類中的專用實用程序函數包括:
AttachParameters:該函數用於將所有必要的 SqlParameter 對象連接到正在運行的 SqlCommand。
AssignParameterValues:該函數用於爲 SqlParameter 對象賦值。
PrepareCommand:該函數用於對命令的屬性(如連接、事務環境等)進行初始化。
ExecuteReader:此專用 ExecuteReader 實現用於通過適當的 CommandBehavior 打開 SqlDataReader 對象,以便最有效地管理與閱讀器關聯的連接的有效期。
SqlHelper體驗談:
以下載自CEOCIO(MVP/CSDN_WEB開發版主)的Blog:
微軟提供的Data Access Application Block中的SQLHelper類中封裝了最常用的數據操作,各個使用者調用他而寫的代碼也有很大區別。
對於一個返回DataSet的方法我原來是這樣寫的:
public DataSet GetDepartmentMemberList(int departmentID)
...{
try
...{
string sql = "OA_Department_GetDepartment_Members";
string conn = ConfigurationSettings.AppSettings["strConnection"];
SqlParameter[] p = 
...{
SqlHelper.MakeInParam("@departmentID",SqlDbType.Int,4,departmentID)
};
DataSet ds = SqlHelper.ExecuteDataset(conn,CommandType.StoredProcedure,sql,p);
return ds;
}
catch(System.Data.SqlClient.SqlException er)
...{
throw new Exception(er.Message);
}
}
現在我是這樣來寫的:
//連接字符串
private string _connectionString = ConfigurationSettings.AppSettings["strConnection"];
public string ConnectionString
...{
get ...{return this._connectionString;}
set ...{this._connectionString = value;}
}
public DataSet GetNewsToIndexPage(int NewsTypeID)
...{
return GetDataSet("yzb_GetNewsToIndexPage",GetNewsToIndexPage_Parameters(NewsTypeID));
}
//設置存儲過程參數
private SqlParameter[] GetNewsToIndexPage_Parameters(int NewsTypeID)
...{
SqlParameter[] p = 
...{
SqlHelper.MakeInParam("@NewsTypeID",SqlDbType.Int,4,NewsTypeID)
};
return p;
}
//這裏才真正調用SqlHelper
private DataSet GetDataSet(string sql, params SqlParameter[] p)
...{
return SqlHelper.ExecuteDataset(ConnectionString,CommandType.StoredProcedure,sql,p);
}
代碼更加靈活,更加安全了:P
做爲一個懶人,大笨狼我經常這樣寫:
System.Data.DataTable dt=SqlHelper.ExecuteDataset(SqlHelper.CONN_STRING_NON_DTC,CommandType.Text,sql).Tables[0]; 
直接返回DataTable, 返回表集合基本不用,只返回一個table用於綁定。
string conn = ConfigurationSettings.AppSettings["strConnection"]; 
我寫在SqlHelper.CONN_STRING_NON_DTC裏面
MakeInParam代碼煩瑣,如果查詢輸入條件不可能有組合SQL, 
我直接exec pronamr paraargs 
如果查詢輸入條件存在安全問題,或者帶返回參數
再用SqlParameter[] queryParam=new SqlParameter[] ...{ 
new SqlParameter("@UserID",SqlDbType.Int) 
}; 
queryParam[0].Value=this.UserID; 
組合sql語句用到@和string.Format技巧.例如:
sql=@"UPDATE Test_User_Statistic
SET 
Test_User_Statistic.[IsQualified]={0}, 
Test_User_Statistic.[Reason]='{1}'
WHERE UserID={2}" ;
sql= string.Format(sql,IsQualified,Reason,userID);
SqlHelper.ExecuteNonQuery(SqlHelper.CONN_STRING_NON_DTC,CommandType.Text,sql);
其中sql語句可以藉助SQL的查詢分析器生成。
這麼幹要保證安全,如果有輸入漏洞,建議還是用SqlParameter[]緩存參數,因爲它會把攻擊性的代碼,比如帶單引號分號的,當作普通字符處理。
superdullwolf(超級大笨狼,每天要自強) 於 2005-6-15 4:52:13 
SqlHelper可以回滾事務,但是我覺得事務還是存儲過程本身來解決比較好:
DBTransaction = CS.BeginTransaction();
SqlHelper.ExecuteNonQuery(DBTransaction, CommandType.StoredProcedure, "pro_T_Accredit_Create", arParams);
p_intOutPut = Convert.ToInt32(arParams[3].Value.ToString());
if(p_intOutPut < 0)
...{
DBTransaction.Rollback(); //--回退事務
}
另外附採用存儲過程回滾
CREATE PROCEDURE 。。。
@idint
。。。。
as
declare 。。。
begin transaction
insert 。。。
delete 。。。
if @@error <> 0 rollback transaction
commit transaction
GO
比較ASP回滾:
標題 在ASP中使用事務控制 julyclyde(原作)
關鍵字 ASP,事務,COM+ 
作者系2月份微軟社區之星Microsoft China Community Star
在編程中,經常需要使用事務。所謂事務,就是一系列必須都成功的操作,只要有一步操作失敗,所有其他的步驟也必須撤銷。比如用ASP開發一個網絡硬盤系統,其用戶註冊部分要做的事有:
將用戶信息記入數據庫
爲用戶開個文件夾用於存儲
初始化用戶操作日誌
這三步必須使用事務,否則萬一磁盤操作失敗,而沒有撤銷數據庫操作,就會造成只能登陸而不能操作的"死用戶"現象。
由於數據庫系統特殊的發展歷史,小至Access,大到DB2,無不帶有事務支持。因此上述步驟可以如下表示:
On Error Resume Next
第一步:
在事務環境下把用戶信息記入數據庫
If Err Then
關閉連接
退出
Else
第二步:創建文件夾
If Err Then
回滾第一步數據庫操作,退出
Else
第三步:在事務環境下操作日誌數據庫
If Err Then
回滾第一步操作,刪除第二步建立的文件夾
退出
End If
End If
End If
提交第一步數據庫操作的事務
提交第二步數據庫操作的事務
End
每一步都需要進行判斷,如果失敗,還需要手工回滾前面多步操作,使程序變得複雜、難懂。如果今後更新了程序,增加其他步驟,還需要嵌套更多層的If...Else...End If,使程序流程更加複雜。
正確的解決辦法是使用ASP的事務控制功能。IIS通過和MTS服務聯繫,可以控制多種支持事務的系統,當程序發出"失敗"的信號時,所有支持事務的系統均將自動回滾,即使操作已經正式完成;對不支持事務的操作也提供了方便的手工回滾方式。上面的例子用ASP事務控制功能重寫如下:
<%@ TRANSACTION = Required %>
On Error Resume Next
Set Conn=Server.CreateObject("ADODB.Connection")
Conn.Open ....
Conn.Execute "INSERT...."
Conn.Close
Set Conn=Nothing
Set Conn2=Server.CreateObject("ADODB.Connection")
Conn2.Open ....
Conn2.Execute "INSERT...."
Conn2.Close
Set Conn2=Nothing
Set FSO=Server.CreateObject("Scripting.FilesystemObject")
FSO.CreateFolder "...."
If Err Then
ObjectContext.SetAbort '通知所有支持事務的組件回滾,並運行手工回滾代碼
Else
ObjectContext.SetComplete
End If
Set FSO=Nothing
Sub OnTransactionAbort
Response.Write "錯誤"
FSO.DeleteFile Server.Mappath("a.txt") 'FSO的手工回滾——刪除文件夾
End Sub
Sub OnTransactionCommit
Response.Write "勝利完成任務"
End Sub
%>
第一行的<%@ TRANSACTION = Required %>表示這一頁ASP文件需要MTS的事務支持。中間的各個操作都按普通順序書寫,而不用考慮回滾問題。在程序最後判斷是否有錯誤。如果有,調用ObjectContext的SetAbort方法,IIS會通過MTS服務通知所有支持事務的組件回滾(主要是數據庫),並且運行Sub OnTransactionAbort對不支持事務的操作手工回滾;如果沒有發生錯誤,調用ObjectContext的SetComplete方法,則會運行Sub OnTransactionCommit來顯示成功的消息。
整個ASP程序不需要爲判斷錯誤和回滾操作書寫多餘的代碼,只須在最後進行判斷,即使今後增加了多步操作,也只需要在Sub OnTransactionAbort中進行控制即可,非常方便,程序員可以專注於過程編寫而不是書寫糾錯代碼。
其實ASP還提供了許多更有用的功能,等着我們使用,千萬不要以爲ASP使用腳本語言,功能就一定弱。
比較ADO回滾:
<% 
'Asp中使用事務
Set conn=Server.CreateObject("ADODB.Connection") 
conn.Open "course_dsn","course_user","course_password" 
conn.begintrans '開始事務
sql="delete from user_info" 
set rs=server.createobject("adodb.recordset") 
rs.open sql,conn,3,3 
if conn.errors.count>0 then '有錯誤發生
conn.rollbacktrans '回滾
set rs=nothing 
conn.close 
set conn=nothing 
response.write "交易失敗,回滾至修改前的狀態!" 
response.end 
else
conn.committrans '提交事務
set rs=nothing 
conn.close 
set conn=nothing 
response.write "交易成功!" 
response.end 
end if
%> 
SqlHelper最開始出現好像是在Microsoft PetShop 作爲DAL層的核心。
另外關於SqlDataReader,我感覺這個東西和ADO裏面的RecordSet類似,就是需要Close.
如果做爲參數和返回值傳遞是比較危險的,因爲你要傳出去就Close(),而究竟在哪裏關閉容易被以往和忽略,所以我覺得還是用強類型的DataSet做爲參數和返回值傳遞紀錄集比較好。
據說下面的寫法不用Close也會自動資源回收,不知道真的假的:
using(SqlDataReader reader=SqlHelper.ExecuteReader(SqlHelper.CONN_STRING_NON_DTC,CommandType.Text,sql))
...{
if(reader.Read())
...{
arr[0]=reader.GetString(1);
。。。。}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章