2013-03-27 74 views
0

我嘗試更新我的對象的一個​​字段,並將其立即保存到數據庫中。意外的樂觀併發異常

using (var ctx = new DataModel(_connectionString)) 
{ 
    var MyObject it = ctx.MyObjects.Where(someConstraint).ToList()[0]; 
    try 
    { 
     //update check time 
     ctx.Refresh(RefreshMode.StoreWins, it); //making sure I have it 
     ctx.AcceptAllChanges(); // in case something else modified it - seems unnecessary 
     it.TimeProperty= DateTime.UtcNow; //Setting the field 
     ctx.DetectChanges(); //seems unnecessary 
     ctx.SaveChanges(SaveOptions.AcceptAllChangesAfterSave); //no SaveOptions changed the behavior 
    } 
    catch (OptimisticConcurrencyException) 
    { 
     _logger.DebugFormat(workerClassName + ": another worker just updated the LastCheckTime"); 
    } 
    //Do some other work and/or sleep 
} 

當我用2個實例以上Azure的模擬器中運行這個,我在這裏得到了很多OptimisticConcurrencyExceptions的。

我想刷新對象,更新其中一個字段,然後將這些更改推送到數據庫。 但是,樂觀併發正在阻止我。

注意:樂觀併發性設置在TimeStamp字段上,我從不接觸。

這是爲什麼,我該如何解決?

回答

1

您可能在此try塊中有多個線程,在從數據庫刷新之後但在其中任何一個保存其更改之前修改它們自己的同一個實體的副本。

試試這個:

using (var ctx = new DataModel(_connectionString)) 
{ 
    bool saved = false; 

    do 
    { 
     var MyObject it = ctx.MyObjects.Where(someConstraint).ToList()[0]; 

     try 
     { 
      it.TimeProperty= DateTime.UtcNow; //Setting the field 
      ctx.SaveChanges(SaveOptions.AcceptAllChangesAfterSave); 

      saved = true; 
     } 
     catch (OptimisticConcurrencyException) 
     { 
      _logger.DebugFormat(workerClassName + ": another worker just updated the LastCheckTime"); 

      ctx.Refresh(RefreshMode.StoreWins, it); 
      ctx.AcceptAllChanges(); 
     } 
    } while(!saved) 
    //Do some other work and/or sleep 
} 

如果這對你的作品,改而條件限制嘗試的數量。

+0

否 - 我有幾個進程執行相同的代碼,但每個進程都是單線程的 – iliaden 2013-03-27 22:38:29

+0

單獨的進程同時修改同一個實體仍然是可能的。遇到異常後處理刷新 – Moho 2013-03-27 22:44:43

+0

我不太在意刷新 - 我需要將其推送到數據庫。在本地,變量'it'在此之後從不使用。 另外 - 我只是用調試器進行檢查:這段代碼在每個進程的單個線程中運行 – iliaden 2013-03-27 22:50:23