2009-05-23 62 views
4

如果一個sql調用失敗,比如說由於死鎖而超時,那麼這個事務就會變成一個殭屍事務 - 我想我的代碼或框架代碼都會執行回滾。 SqlTransaction不爲null,但它是一個殭屍可以拋出一個錯誤,如果你嘗試做一個Rollback()。我找不到.IsZombie屬性。有沒有辦法測試一個潛在的殭屍事務來查看它是否可以回滾?

// Make sure the transaction is not null 
if (transaction != null) 
{ 
    //TODO: Is there a way to test a transaction to see if it can be rolled back? 
    transaction.Rollback(); 
} 

回答

2

你可以嘗試使用TransactionScope類從.NET 2.0的System.Transactions的命名空間。這個類允許你指定一個超時之後事務將被自動取消和回滾。 ADO.NET在.NET 2.0+的TransactionScope的瞭解,並會自動註冊一個DbTransaction的範圍內,如果存在一個當時的數據庫稱爲:

public void DoSomething() 
{ 
    using (TransactionScope scope = new TransactionScope(TransactionScopeOptions.Required, TimeSpan.FromSeconds(60))) 
    { 
     MyDac(); 

     scope.Complete(); // If timeout occurrs, this line is never hit, scope is disposed, which causes rollback if Complete() was not called 
    } 
} 

public class MyDac() 
{ 

    using (SqlConnection ...) 
    { 
     using (SqlCommand ...) 
     { 
      // Do something with ADO.NET here...it will autoenroll if a transaction scope is present 
     } 
    } 
} 

的TransactionScope創建System.Transactions.Transaction內部,如果只涉及一臺服務器,默認情況下允許SQL Server的輕量級事務。如果事務中涉及多個服務器或分佈式資源管理器,則由TransactionScope包裝的事務將被提升爲分佈式事務,這將需要MSDTC進行協調,這可能會使TransactionScope的使用複雜化。如果你所有的事務都是輕量級的,那麼TransactionScope可以提供很多手動管理數據庫事務的好處。

0

您可能要考慮將您的事務處理數據庫的內部代碼,然後可在測試@@ ERROR = 1205,以確定是否你的查詢是死鎖的受害者在這種情況下,您可以重試或ROLLBACK。允許客戶端應用程序創建和管理事務是有點冒險的,如果可能的話避免更好。

希望這有助於

比爾

+0

我希望我可以很容易地切換到主要是服務器端交易。我有500個存儲過程與代碼生成的ADO.NET數據訪問層配對。大多數事務調用已被添加爲樣板。 – MatthewMartin 2009-05-23 13:15:09

1

我乞求你的赦免,但我無法避免不同意。 客戶端事務是使業務過程原子操作成爲可能的原因。 如果您想要將所有事務操作移入數據庫,您總是將業務邏輯移入其中。這是一種方法,但非常不推薦,前提是您將在程序中使用一些稍微複雜的邏輯。 擁有whiles/for/foreach,字符串檢查和其他平凡的操作真的很重要移入數據庫(有時甚至不可能)。然而,死鎖提示似乎非常有用,並且爲客戶端應用程序提供了進一步的控制(這是我認爲最好的方法)。

乾杯

+2

歡迎來到流量堆疊,有趣的點和大多數同意。我不確定你在迴應誰,關於SO的約定是「回答」 - 有些回答和「討論」 - 有些東西與@name一起評論,以澄清收件人。 – MatthewMartin 2009-12-22 15:15:51

相關問題