2015-04-14 17 views
0

在我的C#項目中,我有一個方法,詢問數據庫中是否存在對象,如果不存在,則創建它。現在,如果兩個用戶同時詢問同一個問題,他們都會得到空值,因此流將保存到db,這對於兩個重複項來說是不可能的,所以會引發一個sql異常。 我該如何處理這個問題?c#同時調用sql db

這裏是我的代碼:

var date = DateTime.UtcNow.Date; 


var todayCelebPageView = _celebPageViewsRepo.GetAll().SingleOrDefault(d => d.iCelebId == celebId && d.dDate == date); 

if (todayCelebPageView != null) 
{ 
    todayCelebPageView.iScore++; 

    _celebPageViewsRepo.Save(); 
} 
else 
{ 
    todayCelebPageView = new MovliCelebPageView() {dDate = date, iCelebId = celebId, iScore = 1}; 
    _celebPageViewsRepo.Add(todayCelebPageView); 
    _movliRepository.DbContext.Entry(todayCelebPageView).State = System.Data.EntityState.Added; 
    _celebPageViewsRepo.Save(); 
} 
+0

抓住例外 – stuartd

回答

2

世界上沒有簡單的答案,這是真的,這是與一些解決方案的常見問題。

某些選項可能是:

  1. 趕上正確的SQL異常,並相應地重試
  2. 創建的數據庫調用一個隊列,並處理它們一次一個
  3. 的一些實施或者在數據庫中進行鎖定(可能通過將其封裝在事務中)或代碼本身。

還有一件事要考慮的是,如果兩次嘗試同時創建一條記錄,應該從業務角度出發。

創建記錄的人最後一次勝利了嗎?第一個人應該贏,第二個應該得到一個錯誤?或者你應該寫第一條記錄,並用第二條記錄再次更新?

對此的回答完全取決於您在應用程序中所做的具體操作。

+0

我應該在這種情況下使用鎖對象嗎? –

0

移動檢查的邏輯和創造的過程級別,那麼它將被事務隔離處理:

IF NOT EXISTS (SELECT 'non-empty' FROM sys.objects WHERE object_id = OBJECT_ID(N'dbo.TABLE_NAME') AND type in (N'U')) 
    CREATE TABLE dbo.TABLE_NAME 

但是你還是要包裝你的方法和依據的SqlExceptionNumber財產處理異常:

using (SqlConnection connection = new SqlConnection(connectionString)) 
{ 
    SqlCommand command = new SqlCommand(queryString, connection); 
    try 
    { 
     command.Connection.Open(); 
     command.ExecuteNonQuery(); 
    } 
    catch (SqlException ex) 
    { 
     for (int i = 0; i < ex.Errors.Count; i++) 
     { 
      errorMessages.Append("Index #" + i + "\n" + 
       "Message: " + ex.Errors[i].Message + "\n" + 
       "LineNumber: " + ex.Errors[i].LineNumber + "\n" + 
       "Source: " + ex.Errors[i].Source + "\n" + 
       "Procedure: " + ex.Errors[i].Procedure + "\n"); 
     } 
     Console.WriteLine(errorMessages.ToString()); 
    } 
} 

System Error Messages
Cause and Resolution of Database Engine Errors

0

您應該將存在和插入的測試包裝在事務中。這樣第二次檢查是否存在會阻止第一次完成。