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();
}
}
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();
}
}
在分佈式應用程序中,往往要同時操作多個數據庫,使用數據庫事務就不能滿足業務的要求了。在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命令就可以了