2012-12-07 80 views
1

我一直在谷歌搜索過去幾個小時的答案,但還沒有找到答案,所以我希望有人能在這裏指出我在正確的方向。TransactionScope,EF DbContext和髒讀

我想知道如何在TransactionScope中使用EF DbContext(代碼優先)進行髒讀。例如

DbContext context = new MyEntities(); 
using(TransactionScope scope = new TransactionScope()) 
{ 
    context.SomeTable.Add(someObject); 
    context.SaveChanges(); 

    var objects = context.SomeTable.Where(...).Select(...); //times out here on the read, because the write above locks the tables 
    //modify each object 
    context.SaveChanges(); 

    scope.Complete(); //transaction is a success only if the entire batch succeeds 
} 

我試圖用包裹下的讀取調用:

using(TransactionScope scope2 = new TransactionScope(TransactionScopeOption.RequiresNew, new TransactionOptions{IsolationLEvel = IsolationLevel.ReadUncommitted})) 
{ 
    var objects = context.SomeTable.Where(...).Select(...); //times out here on the 
} 

什麼是正確的做法?

+0

你用什麼關係數據庫管理系統?通常編寫者不應該阻止讀者,除非它是SQLServer。但即使對於SQLServer,也有比使用髒讀更好的解決方案 - 您可以爲數據庫啓用「READ_COMMITTED_SNAPSHOT」。 – a1ex07

+0

此外,它看起來像捕魚插入的對象的ID,有更容易的方法來做到這一點,而不是在插入後選擇它。是這樣嗎? – SmartK8

+0

「在讀取時超時,因爲上面的寫入鎖定表」當然不是因爲讀取發生在同一個事務中。爲什麼會阻止自己?此外,寫入不會鎖定整個表格(這是一個神話)。 – usr

回答

0

您可以在服務器上執行alter database your_db_name set READ_COMMITTED_SNAPSHOT on;(可從SQLServer 2005獲得),並且讀寫器不會被寫入器阻塞(假設讀取事務的隔離級別爲read committed)。

+0

啊,是的,這聽起來最合乎邏輯...目前它已關閉,我會請DBA爲我改變這個... – Alfred

1

它最終點擊了我的問題是什麼問題是:EF沒有與L2S很好地整合TransactionScope的方式。這意味着EF打開和關閉每個需要服務器的操作的連接(保存更改或查詢)。

這可以讓你的分佈式事務和分佈式死鎖。

要解決此問題,請手動打開並關閉EF StoreConnection以確保在事務處理期間只有一個連接。

1

您可以設置爲IsolationLevel將TransactionScope的是這樣的...

var transactionOptions = new System.Transactions.TransactionOptions(); 
transactionOptions.Timeout = new TimeSpan(0, 0, 30); 
transactionOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted; 
using (var transactionScope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required, transactionOptions)) 
{ 
... 
}