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 が発生します。

オブジェクトを更新し、そのフィールドの 1 つを更新してから、それらの変更をデータベースにプッシュしようとしています。ただし、楽観的同時実行が妨げられています。

注: オプティミスティック コンカレンシーは、私が触れたことのない TimeStamp フィールドに設定されています。

それはなぜですか、どうすれば修正できますか?

4

1 に答える 1

1

この try ブロック内に複数のスレッドがあり、両方が DB から更新された後、どちらかが変更を保存する前に、同じエンティティの独自のコピーを変更する可能性があります。

これを試して:

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
}

これでうまくいく場合は、while 条件を変更して試行回数を制限してください。

于 2013-03-27T22:35:49.813 に答える