c#事務的使用、樣本及注意事項 轉

來源:互聯網
上載者:User
一、事務的介紹

.NET Framework 開發員指南
事務是一組組合成邏輯工作單元的操作,雖然系統中可能會出錯,但事務將控制和維護事務中每個操作的一致性和完整性。
例如,在將資金從一個帳戶轉移到另一個帳戶的銀行應用中,一個帳戶將一定的金額貸記到一個資料庫表中,同時另一個帳戶將相同的金額借記到另一個資料庫表中。由於電腦可能會因停電、網路中斷等而出現故障,因此有可能更新了一個表中的行,但沒有更新另一個表中的行。如果資料庫支援事務,則可以將資料庫操作組成一個事務,以防止因這些事件而使資料庫出現不一致。如果事務中的某個點發生故障,則所有更新都可以復原到事務開始之前的狀態。如果沒有發生故障,則通過以完成狀態提交事務來完成更新。
在 ADO.NET 中,可以使用 Connection 和 Transaction 對象來控制事務。可以使用 Connection.BeginTransaction 啟動本地事務。一旦開始一個事務,就可以使用 Command 對象的 Transaction 屬性在該事務中登記命令。然後,可以根據事務組件的成功或失敗情況,使用 Transaction 對象提交或復原在資料來源中所做的修改。
還可以使用 Connection.EnlistDistributedTransaction 在現有的分散式交易中登記。在現有的分散式交易中登記可以確保當提交或復原整個分散式交易時,也提交或復原對資料來源所作的代碼修改。
以下樣本建立一個 OleDbConnection 和一個 OleDbTransaction。它還示範了如何使用 BeginTransaction、Commit 和 Rollback 方法。

public void RunOleDbTransaction(string myConnString)
{
OleDbConnection myConnection = new OleDbConnection(myConnString);
myConnection.Open();
OleDbCommand myCommand = myConnection.CreateCommand();
OleDbTransaction myTrans;
// Start a local transaction
myTrans = myConnection.BeginTransaction(IsolationLevel.ReadCommitted);
// Assign transaction object for a pending local transaction
myCommand.Connection = myConnection;
myCommand.Transaction = myTrans;
try
{
myCommand.CommandText = /"Insert into Region (RegionID, RegionDescription) VALUES (100, /'Description/')/";
myCommand.ExecuteNonQuery();
myCommand.CommandText = /"Insert into Region (RegionID, RegionDescription) VALUES (101, /'Description/')/";
myCommand.ExecuteNonQuery();
myTrans.Commit();
Console.WriteLine(/"Both records are written to database./");
}
catch(Exception e)
{
try
{
myTrans.Rollback();
}
catch (OleDbException ex)
{
if (myTrans.Connection != null)
{
Console.WriteLine(/"An exception of type /" + ex.GetType() +
/" was encountered while attempting to roll back the transaction./");
}
}
Console.WriteLine(/"An exception of type /" + e.GetType() +
/" was encountered while inserting the data./");
Console.WriteLine(/"Neither record was written to database./");
}
finally 
{
myConnection.Close();
}
}

OleDbTransaction.Commit 方法 
提交資料庫事務。
public virtual void Commit(); 
OleDbTransaction.Rollback 方法
從掛起狀態復原事務。
public virtual void Rollback();
OleDbConnection.BeginTransaction 方法 
開始資料庫事務。
public OleDbTransaction BeginTransaction();
以當前的 IsolationLevel 值開始資料庫事務。
public OleDbTransaction BeginTransaction(IsolationLevel); 
IsolationLevel 枚舉?
指定串連的事務鎖定行為。 在執行事務時,.NET Framework 資料提供者使用 IsolationLevel 值。在顯式更改之前,IsolationLevel 保持有效,但是可以隨時對它變更。新值在執行時使用,而不是在分析時使用。如果在事務期間更改,伺服器的預期行為是,對其餘所有語句應用新的鎖定層級。
IsolationLevel成員 ReadCommitted 
在正在讀取資料時保持共用鎖定,以避免髒讀,但是在事務結束之前可以更改資料,從而導致不可重複的讀取或幻像資料。 
OleDbConnection.CreateCommand 方法 
建立和返回一個與 OleDbConnection 相關聯的 OleDbCommand 對象。
public OleDbCommand CreateCommand();
OleDbCommand.Connection 屬性 
擷取或設定 OleDbCommand 的此執行個體使用的 OleDbConnection。
public OleDbConnection Connection {get; set;}

如何在.NET中實現事務(1) 
 
如何在.NET中實現事務機制呢? 通常可以使用2種方式: 直接寫入到sql 中;使用ADO.NET 實現。下面依次作一下介紹: 
方法1:直接寫入到sql 中 
使用 BEGIN TRANS, COMMIT TRANS, ROLLBACK TRANS 實現: 
例如 
BEGIN TRANS 
DECLARE @orderDetailsError int, @productError int 
DELETE FROM /"Order Details/" WHERE ProductID=42 
SELECT @orderDetailsError = @@ERROR 
DELETE FROM Products WHERE ProductID=42 
SELECT @productError = @@ERROR 
IF @orderDetailsError = 0 AND @productError = 0 
COMMIT TRANS 
ELSE 
ROLLBACK TRANS 
這種方法比較簡單,具體可以查閱相關sql server 協助

方法2 :使用ADO.NET 實現,使用這種方式的優點是可以在中介層來管理事務,當然你也可以選擇在資料層來實現。 
SqlConnection 和OleDbConnection 對象有一個 BeginTransaction 方法,它可以返回 SqlTransaction 或者OleDbTransaction 對象。而且這個對象有 Commit 和 Rollback 方法來管理事務,具體例子如下:

cnNorthwind.Open() 
Dim trans As SqlTransaction = cnNorthwind.BeginTransaction() 
Dim cmDel As New SqlCommand() 
cmDel.Connection = cnNorthwind 
cmDel.Transaction = trans
Try 
cmDel.CommandText = _ 
/"DELETE [Order Details] WHERE ProductID = 42/" 
cmDel.ExecuteNonQuery() 
cmDel.CommandText = /"DELETE Products WHERE ProductID = 42/" 
cmDel.ExecuteNonQuery() 
trans.Commit()
Catch Xcp As Exception 
trans.Rollback() 
Finally 
cnNorthwind.Close() 
End Try

Ok,通過上面的例子可以實現與方法1同樣的效果。

並發問題:

如果沒有鎖定且多個使用者同時訪問一個資料庫,則當他們的事務同時使用相同的資料時可能會發生問題。並發問題包括: 丟失或覆蓋更新,未確認的相關性(髒讀),不一致的分析(非重複讀),幻像讀。但是如何來避免資料讀取時髒讀等問題出現呢? 
 
二、事務執行個體
using(SqlTransaction trans = conn.BeginTransaction())
{
  try
  {
 //迴圈進行資訊的插入
 for(int count = 0; count < applyInfo.Length; count ++)
 {
   //聲明參數並賦值
   SqlParameter[] parms = 
{ Database.MakeInParam (/"@Stu_ID/",System.Data.SqlDbType.VarChar,11,applyInfocount].StuID),
Database.MakeInParam/"@Bank_Name/",System.Data.SqlDbType.VarChar,50,applyInfo[count].BankName),  Database.MakeInParam/"@Apply_Loan_Money/",System.Data.SqlDbType.Money,8,applyInfo[count].ApplyLoanMoney), Database.MakeInParam(/"@Apply_Loan_Year/",System.Data.SqlDbType.VarChar,20,applyInfo[count].ApplyLoanYear),  Database.MakeInParam/"@Apply_Year/",System.Data.SqlDbType.Char,6,applyInfo[count].ApplyYear),       Database.MakeInParam(/"@Apply_Length/",System.Data.SqlDbType.Int,4,applyInfo[count].ApplyLength),       Database.MakeInParam(/"@Apply_Pass/",System.Data.SqlDbType.Char,1,applyInfo[count].ApplyPass),
Database.MakeInParam(/"@Apply_Remark/",System.Data.SqlDbType.VarChar,100,applyInfo[count].ApplyRemark)
        };
  //執行新增操作
  SqlHelper.ExecuteNonQuery(trans,CommandType.StoredProcedure, /"ApplyInfo_Create/", parms);
}
      //未出現錯誤,則提交事務
   trans.Commit();
   return true;
   }
       catch(Exception ex)
   {
  //出錯則復原
  trans.Rollback();
  throw ex;
       }
 }
四、注意事項
  事務的定義必須在串連開啟後,提交必須在關閉以前
  使用事務時必須即是把事務添加到sqlCommand中去。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.