0

試圖更好地理解隔離級別 - 使用實體框架和SQL Server最佳的隔離級別爲特定應用

什麼會被用於以下情形推薦使用的隔離級別 -

的網上訂票系統的飛行說門票或活動門票

方案 -

讓我們假設事件的容量爲100 - 僞代碼是弗洛WS

Begin transaction 
    If SeatCount < 100 
    SeatCount = SeatCount + 1 
    End transaction 

編輯 - 響應評論這裏是我的pseudeocode會是什麼樣子的實際代碼。我沒有代碼,我只是想更好地理解這種情況。讓我們說,你有兩個表「事件」,你有兩列 - 「名稱,席位預訂」和一張桌子票,你有單獨的票詳情。

  bool tSuccess = false; 
     //this transactionscope resolves to serializable 
     using (TransactionScope transaction = new TransactionScope()    
     {     
      try{ 
      if(objectcontext.event.SeatsBooked < 100) 
      { 
       objectcontext.event.SeatsBooked = objectcontext.event.SeatsBooked + 1; 
       ticket newTicket = new ticket{ 
       }; 
       objectcontext.tickets.AddObject(newTicket); 
       objectcontext.SaveChanges(); 
      } 
      } 
      catch(Exception e) 
      { 
       //log and return 
      } 
     } 
     if (tSuccess) 
     { 
      bd.AcceptAllChanges(); 
     } 

在這種情況下是正常的假設,提交讀或可重複讀會導致超量預訂或丟失更新,因爲這兩筆交易可以爲同一個座位競爭。

推薦使用可串行化的方法嗎?

+0

它現在甚至查詢,我們看一些實際的代碼,你要投入交易 – WKordos

+0

你可以使用如下語句'更新SeatsBooked設置SeatsBooked =情況下SeatsBooked + @SeatsRequested <= TotalSeats然後SeatsBooked + @SeatsRequested其他SeatsBooked結束在哪裏Name = @ Name'來處理測試並在一次操作中更新。 'output'子句可以提供之前和之後的值。仍然需要適當的隔離級別。 – HABO

回答

2

可重複讀取是必需的,可序列化是沒有必要的。可重複讀取可確保更新將看到與先前選擇相同的座位數。不過,您的TransactionScope需要跨越整個邏輯工作單元。不只是寫。

在原始SQL中,使用WITH (UPDLOCK, HOLDLOCK)會更加優雅,但EF不適用。

如果發生衝突,很容易發生死鎖。請重試整個邏輯交易或使用UPDLOCK進行選擇。 UPDLOCK將完全避免死鎖。

+2

+1我寫了一篇關於如何工作的文章:[Entity framework and pessimistic concurrency](http://www.ladislavmrnka.com/2012/09/entity-framework-and-pessimistic-concurrency/) –

+0

@LadislavMrnka - 偉大的文章。這清除了很多混亂。如果你已經寫了關於表值函數的文章,請你分享一下這個鏈接。非常感謝。 – user529265