以下示例創建一個 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中去。
另外,以下是一段在LINQ中實現的事務:
if (ctx.Connection != null) ctx.Connection.Open();
DbTransaction tran = ctx.Connection.BeginTransaction();
ctx.Transaction = tran;
try
{
CreateTest(new tbTest {ID=3,Name="妹子" });
CreateTest(new tbTest {ID=2,Name="哥們" });//因為ID=2已經存在,所以程序出錯跳向Catc