net中的4種事務總結
在一個MIS
系統中,沒有用事務那就絕對是有問題的,要麼就只有一種情況:你的系統實在是太小了,業務業務邏輯有隻要一步執行就可以完成了。因此掌握事務處理的方法是很重要,進我的歸類在.net
中大致有以下4種事務處理的方法。大家可以參考一下,根據實際選擇適當的事務處理。
1 SQL事務
sql
事務是使用SQL server
自身的事務:在儲存過程中直接使用Begin Tran
,Rollback Tran
,Commit Tran
實現事務:
優點:執行效率最佳
限制:事務上下文僅在資料庫中呼叫,難以實現複雜的業務邏輯。
Demo:(所有demo
,都以SQL Server
自帶的Northwind
資料的表Region
為例)
CREATE PROCEDURE dbo.SPTransaction
(
@UpdateID int,
@UpdateValue nchar(50),
@InsertID int,
@InsertValue nchar(50)
)
AS
begin Tran
Update Region Set RegionDescription=@UpdateValue where RegionID=@UpdateID
insert into Region Values (@InsertID,@InsertValue)
declare @RegionError int
select @RegionError=@@error
if(@RegionError=0)
COMMIT Tran
else
ROLLBACK Tran
GO
/// <summary>
/// SQL事務:
/// </summary>
public void SQLTran()
{
SqlConnection conn = new SqlConnection("Data Source=127.0.0.1;Initial Catalog=Northwind;Persist Security Info=True;User ID=sa;Password=123;");
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "SPTransaction";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = conn;
conn.Open();
SqlParameter[] paras= new SqlParameter[]{
new SqlParameter ("@UpdateID",SqlDbType.Int,32),
new SqlParameter ("@UpdateValue",SqlDbType .NChar,50),
new SqlParameter ("@InsertID",SqlDbType.Int ,32),
new SqlParameter ("@InsertValue",SqlDbType.NChar ,50)};
paras[0].Value = "2";
paras[1].Value = "Update Value1";
paras[2].Value = "6";
paras[3].Value = "Insert Value1";
foreach (SqlParameter para in paras )
{
cmd.Parameters.Add(para);
}
cmd.ExecuteNonQuery();
}
2 ADO.net事務
Ado.net事務可能是大家一般都用的
優點:簡單,效率和資料庫事務差不多。
缺點:事務不能跨資料庫,只能在一個資料庫連線上。如果是兩個資料庫上就不能使用該事務了。
Demo:
/// <summary>
/// 一般的ADO.net 事務
/// </summary>
public void ADONetTran1()
{
SqlConnection conn = new SqlConnection("Data Source=127.0.0.1;Initial Catalog=Northwind;Persist Security Info=True;User ID=sa;Password=123;");
SqlCommand cmd = new SqlCommand();
try
{
cmd.CommandText = "Update Region Set RegionDescription=@UpdateValue where RegionID=@UpdateID";
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
conn.Open();
SqlParameter[] paras = new SqlParameter[]{
new SqlParameter ("@UpdateID",SqlDbType.Int,32),
new SqlParameter ("@UpdateValue",SqlDbType .NChar,50)};
paras[0].Value = "2";
paras[1].Value = "Update Value12";
foreach (SqlParameter para in paras)
{
cmd.Parameters.Add(para);
}
//開始事務
cmd.Transaction = conn.BeginTransaction();
cmd.ExecuteNonQuery();
cmd.CommandText = "insert into Region values(@InsertID,@InsertValue)";
cmd.CommandType = CommandType.Text;
paras = new SqlParameter[]{
new SqlParameter ("@InsertID",SqlDbType.Int ,32),
new SqlParameter ("@InsertValue",SqlDbType.NChar ,50)};
paras[0].Value = "7";
paras[1].Value = "Insert Value";
cmd.Parameters.Clear();
foreach (SqlParameter para in paras)
{
cmd.Parameters.Add(para);
}
cmd.ExecuteNonQuery();
//提交事務
cmd.Transaction.Commit();
}
catch
{
//回滾事務
cmd.Transaction.Rollback();
throw;
}
finally
{
conn.Close();
}
}
3 TransactionScope事務
TransactionScope
事務類,它可以使程式碼塊成為事務性程式碼。並自動提升為分散式事務
優點:實現簡單,同時能夠自動提升為分散式事務
Demo:
/// <summary>
/// TransactionScope事務:可自動提升事務為完全分散式事務的輕型(本地)事務。
/// 使用時要保證MSDTC服務(控制分佈事務)是開啟的可以使用:net start msdtc命令開啟服務;
/// </summary>
public void ADONetTran2()
{
SqlConnection conn = new SqlConnection("Data Source=127.0.0.1;Initial Catalog=Northwind;Persist Security Info=True;User ID=sa;Password=123;");
SqlCommand cmd = new SqlCommand();
try
{
using (System.Transactions.TransactionScope ts = new TransactionScope())
{
cmd.CommandText = "Update Region Set RegionDescription=@UpdateValue where RegionID=@UpdateID";
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
conn.Open();
SqlParameter[] paras = new SqlParameter[]{
new SqlParameter ("@UpdateID",SqlDbType.Int,32),
new SqlParameter ("@UpdateValue",SqlDbType .NChar,50)};
paras[0].Value = "2";
paras[1].Value = "Update Value12";
foreach (SqlParameter para in paras)
{
cmd.Parameters.Add(para);
}
cmd.ExecuteNonQuery();
cmd.CommandText = "insert into Region values(@InsertID,@InsertValue)";
cmd.CommandType = CommandType.Text;
paras = new SqlParameter[]{
new SqlParameter ("@InsertID",SqlDbType.Int ,32),
new SqlParameter ("@InsertValue",SqlDbType.NChar ,50)};
paras[0].Value = "8";
paras[1].Value = "Insert Value";
cmd.Parameters.Clear();
foreach (SqlParameter para in paras)
{
cmd.Parameters.Add(para);
}
cmd.ExecuteNonQuery();
//提交事務
ts.Complete();
}
}
catch
{
throw;
}
finally
{
conn.Close();
}
}
4 COM+事務
在分散式應用程式中,往往要同時操作多個資料庫,使用資料庫事務就不能滿足業務的要求了。在COM+
中,提供完整的事務處理服務。很方便處理多個資料庫上的事務。
Demo:
/// <summary>
/// COM+事務
/// </summary>
public void ComTran()
{
SqlConnection conn = new SqlConnection("Data Source=127.0.0.1;Initial Catalog=Northwind;Persist Security Info=True;User ID=sa;Password=123;");
SqlCommand cmd = new SqlCommand();
ServiceConfig sc = new ServiceConfig();
//指定事務型別
sc.Transaction = TransactionOption.Required;
//設定啟動跟蹤
sc.TrackingEnabled = true;
//建立一個上下文,該上下文的配置由作為 cfg 引數傳遞的 ServiceConfig 物件來指定。
//隨後,客戶端和伺服器端的策略均被觸發,如同發生了一個方法呼叫。
//接著,新的上下文被推至上下文堆疊,成為當前上下文
ServiceDomain.Enter(sc);
try
{
cmd.CommandText = "Update Region Set RegionDescription=@UpdateValue where RegionID=@UpdateID";
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
conn.Open();
SqlParameter[] paras = new SqlParameter[]{
new SqlParameter ("@UpdateID",SqlDbType.Int,32),
new SqlParameter ("@UpdateValue",SqlDbType .NChar,50)};
paras[0].Value = "2";
paras[1].Value = "Update Value22";
foreach (SqlParameter para in paras)
{
cmd.Parameters.Add(para);
}
cmd.ExecuteNonQuery();
cmd.CommandText = "insert into Region values(@InsertID,@InsertValue)";
cmd.CommandType = CommandType.Text;
paras = new SqlParameter[]{
new SqlParameter ("@InsertID",SqlDbType.Int ,32),
new SqlParameter ("@InsertValue",SqlDbType.NChar ,50)};
paras[0].Value = "9";
paras[1].Value = "Insert Value";
cmd.Parameters.Clear();
foreach (SqlParameter para in paras)
{
cmd.Parameters.Add(para);
}
cmd.ExecuteNonQuery();
//提交事務
ContextUtil.SetComplete();
}
catch
{
//回滾事務
ContextUtil.SetAbort();
throw;
}
finally
{
conn.Close();
//觸發伺服器端的策略,隨後觸發客戶端的策略,如同一個方法呼叫正在返回。
//然後,當前上下文被彈出上下文堆疊,呼叫 Enter 時正在執行的上下文成為當前的上下文。
ServiceDomain.Leave();
}
}
在.net
中還有些也能進行事務處理,如web Service
中
需要特別補充的是:
如果你使用的是分佈事務(TransactionScope
事務和COM+
事務),在預設情況下你是要重新配置安裝SQL Server
資料庫伺服器和訪問資料庫的客戶端的.(如果沒有配置執行會出現以下錯誤:該夥伴事務管理器已經禁止了它對遠端/網路事務的支援。 (異常來自 HRESULT:0x8004D025)
)下面是MSDN上關於配置分散式事務的一段原話:
配置分散式事務
要啟用分散式事務,可能需要通過網路啟用 MS DTC
,以便在使用應用了最新的 Service Pack
的較新作業系統(例如 Windows XP 或 Windows 2003)時使用分散式事務。如果啟用了 Windows 防火牆(Windows XP Service Pack 2 的預設設定),必須允許 MS DTC
服務使用網路或開啟 MS DTC
埠。
實際怎麼配置呢,經過我的實際使用:大致如下:開啟’控制皮膚’->’管理工具’->’元件服務’,點開’元件服務’->’計算機’->’我的電腦’,在’我的電腦’上右擊屬性,點’MSDTC
‘,然後點’安全性配置’。作為資料庫的伺服器的配置如下:
而訪問資料庫的客戶端的配置和伺服器端的稍有些差別:
在設定完上面的還有使防火牆MS DTC
服務使用網路或開啟 MS DTC
埠:執行netsh firewall set allowedprogram %windir%/system32/msdtc.exe MSDTC enable
命令就可以了
ASP.NET中的自動化事務
通過在ASP.NET
頁面中新增Transaction
屬性,可使得ASP.NET
能夠在系統中支援自動事務。利用Transaction
屬性,開發人員能夠指示頁面參與現有事務,開始新事務,或者不參與事務。下表列舉了ASP.NET
中可用的Transaction
屬性值。
通過在程式碼中的Page指令中設定Transaction屬效能夠定義頁面支援的事務級別。例如,插入以下指令能夠保證頁面活動總是在事務範圍中執行:
<%@ Page Transaction="Required" %>
如果省略Transaction
屬性,頁面則禁用事務。使用System.EnterpriseServices.ContextUtil
類的靜態方法在ASP.NET
頁面中提交或者放棄事務。這些靜態方法是SetComplete()
和SetAbort()
(它們分別對應Page
事件CommitTransaction()
和AbortTransaction()
)。以下程式碼列舉了頁面實現框架,該頁面將Page
指令的Transaction
屬性設定為Required
,同時在CommitTransaction()
和AbortTransaction()
事件中,編寫處理事務結果所需的程式碼。
void Page_Load(object sender, System.EventArgs e)
{
AbortTransaction += new System.EventHandler(AbortTransactionEvent);
CommitTransaction += new System.EventHandler(CommitTransactionEvent);
try
{
/* 在這裡放置事務性程式碼 */
ContextUtil.SetComplete();
}
catch (Exception)
{
ContextUtil.SetAbort();
}
}
void AbortTransactionEvent(object sender, System.EventArgs e)
{
/*用於回滾行為的程式碼*/
}
void CommitTransactionEvent(object sender, System.EventArgs e)
{
/*用於提交行為的程式碼*/
}
}
4. 何時使用事務
雖然.NET 2.0
對事務提供了很好的支援,但是沒有必要總是使用事務。使用事務的第一條規則是,在能夠使用事務的時候都應該使用事務,但是不要使用過度。原因在於,每次使用事務,都會佔用一定的開銷。另外,事務可能會鎖定一些表的行。還有一條規則是,只有當操作需要的時候才使用事務。例如,如果只是從資料庫中查詢一些記錄,或者執行單個查詢,在大部分時候都不需要使用顯式事務。
開發人員應該在頭腦中始終保持一個概念,就是用於修改多個不同表資料的冗長事務會嚴重妨礙系統中的所有其他使用者。這很可能導致一些效能問題。當實現一個事務時,遵循下面的實踐經驗能夠達到可接受的結果:(1)避免使用在事務中的SELECT
返回資料,除非語句依賴於返回資料;(2)如果使用SELECT
語句,只選擇需要的行,這樣不會鎖定過多的資源,而儘可能的提高效能;(3)儘量將事務全部寫在T-SQL
或者API
中;(4)避免事務與多重獨立的批處理工作結合,應該將這些批處理放置在單獨的事務中;(5)儘可能避免大量更新。
另外,必須注意的一點就是事務的預設行為。在預設情況下,如果沒有顯式的提交事務,則事務會回滾。雖然預設行為允許事務的回滾,但是顯式回滾方法總是一個良好的程式設計習慣。這不僅僅只是釋放鎖定資料,也將使得程式碼更容易讀並且更少錯誤。
相關文章
- ado.net中事務的使用
- Spring事務管理總結Spring
- mysql總結(二)-事務MySql
- 分散式事務總結分散式
- 五種分散式事務解決方案(圖文總結)分散式
- 資料庫事務與 MySQL 事務總結資料庫MySql
- Redis中的事務處理機制分析與總結Redis
- .Net Core中依賴注入服務使用總結依賴注入
- .NET 資料庫事務的各種玩法進化資料庫
- 事務知識點總結
- 原創:oracle 事務總結Oracle
- mysql鎖與事務總結MySql
- [資料庫]事務的4種隔離級別資料庫
- MySQL 事務常見面試題總結 | JavaGuide 稽核中MySql面試題JavaGUIIDE
- 微服務分散式事務4種解決方案實戰微服務分散式
- 資料庫系列:事務的4種隔離級別資料庫
- JS中this的4種繫結規則JS
- mysql事務對效率的影響分析總結JILEMySql
- C# Log4net配置檔案 總結C#
- Latex 中勾的幾種畫法總結
- LaTeX中各種常用盒子的使用總結
- MySQL 事務、日誌、鎖、索引學習總結,MySql索引
- golang 中的四種型別轉換總結Golang型別
- caffe中各種cblas的函式使用總結函式
- 事務4大特性
- Spring事務配置的五種方式Spring
- MySQL事務細枝末節總結與分析[更新]MySql
- oracle 中的事務Oracle
- MongoDB 中的事務MongoDB
- MyBatis中的事務MyBatis
- Redis 中的事務Redis
- Vue 中實現雙向繫結的 4 種方法Vue
- ADO.NET 總結
- 前端 JavaScript 中的三種 for 迴圈語句總結前端JavaScript
- Maven-POM中的各種scope的行為總結Maven
- Laravel 事務中 使用 悲觀鎖 小結Laravel
- .Net防sql注入的方法總結SQL
- Spring事務失效的一種原因(this呼叫)Spring