2012-05-22 152 views
1

我首先使用EF代碼。最近,我不得不更換下面的代碼:與首次使用EF代碼時鎖定資源事務死鎖

Context.ExecuteSqlCommand("IF NOT EXISTS(SELECT 1 FROM Users WHERE Email = '{0}') 
          INSERT INTO Users(Email, CreatedAt) 
          VALUES ('email', GETDATE())"); 

User user = userRepository.GetByEmail("[email protected]"); 

if (user == null) 
{ 
    user = New User { Email = email, CreatedAt = DateTime.Now }; 

    userRepository.Add(user); 
    unitOfWork.Commit(); 
} 

這背後的原因是,它EF花了很長的時間來運行第一段代碼嘗試添加數以千計的時行。通過將其更改爲ExecuteSqlCommand,處理多行的時間減少了很多。

我現在看到的問題(僅發生兩次)是來自數據庫的以下消息:事務(進程ID 52)在鎖資源上與另一個進程死鎖並被選作死鎖犧牲品。重新運行交易。

我該如何解決這個問題?我的大部分數據訪問都是通過EF完成的,只有上面的例外。我從未在日誌中看到過死鎖,所以我認爲這與查詢有關。

我的問題是:

  1. 有編寫使用無鎖的查詢的方法嗎?那個 查詢怎麼樣?
  2. 有沒有辦法告訴EF使用NO LOCK進行某些查詢?

回答

0

你真正想要的是先鎖定表,而不是防止鎖定。鎖定是必要的,以確保在您的命令中的兩個語句之間,某個其他進程尚未出現並插入相同的用戶。 (鎖定因爲物理存儲正在被修改插入數據時總是必要的。)

假設這實際上是導致死鎖的命令,以下應該解決它,因爲它僅要求輸入的排他鎖:

Context.ExecuteSqlCommand(「IF NOT EXISTS(SELECT 1 FROM Users WHERE Email ='{0}') INSERT INTO Users(Email,CreatedAt) VALUES('email',GETDATE())」);