18

いくつかの潜在的な例外を処理するときcontext.SaveChanges()、例外の 1 つがOptimisticConcurrency. これに関する Microsoft のドキュメントhttp://msdn.microsoft.com/en-us/library/bb399228.aspxでは、EF 4.x についてこれについて説明しています ...

try
{
    // Try to save changes, which may cause a conflict.
    int num = context.SaveChanges();
    Console.WriteLine("No conflicts. " +
        num.ToString() + " updates saved.");
}
catch (OptimisticConcurrencyException)
{
    // Resolve the concurrency conflict by refreshing the 
    // object context before re-saving changes. 
    context.Refresh(RefreshMode.ClientWins, orders);

    // Save changes.
    context.SaveChanges();
    Console.WriteLine("OptimisticConcurrencyException "
    + "handled and changes saved");
}

Refresh()...しかし、EF 5.0 (RC) では、私の EF5、コードファースト、DbContext 派生contextクラスには存在しないため、これは機能しないようです。

わかりますcontext.Entry(context.SalesOrderHeaders).Reload();-しかし、それは更新/マージではなく、まっすぐなdbからのリロードであるように見えます(ポリシークライアントが勝つ)。

EF5 でオプティミスティック同時実行例外を処理する方法はありますか? 実際には、SaveChanges() での例外処理に関する一般的なポインターでさえいいでしょう

ありがとう

4

2 に答える 2

31

DbContext API で同時実行例外を解決する方法は、元のエンティティをリロードします。

catch (DbUpdateConcurrencyException ex)
{
    // Get failed entry
    var entry = ex.Entries.Single(...);
    // Overwrite original values with values from database but don't
    // touch current values where changes are held
    entry.OriginalValues.SetValues(entry.GetDatabaseValues());
}

上記のコードを使用することもできますが、ObjectContextインスタンスからインスタンスを取得する必要がありDbContextます (これは単なるラッパーObjectContextです)。

catch (DbUpdateConcurrencyException ex)
{
    var objContext = ((IObjectContextAdapter)context).ObjectContext;
    // Get failed entry
    var entry = ex.Entries.Single(...);
    // Now call refresh on ObjectContext
    objContext.Refresh(RefreshMode.ClientWins, entry.Entity);        
}

あなたも試すことができます:

objContext.Refresh(RefreshMode.ClientWins, ex.Entries.Select(e => e.Entity));
于 2012-08-02T07:34:10.067 に答える
1

変更が 1 つのエンティティ (特定の 1 行で、他のテーブルなどではない) に対してのみ行われる場合は、コンカレンシー メカニズムによってカバーされ、古いものを破棄して新しいものを作成することでコンテキストを更新できます。問題は、変更されたエンティティごとにコンテキストが破棄され、まだコミットされていないエンティティがコンテキストから切り離され、変更が失われることです。そのため、ユニットワークの範囲に注意してください。

    catch (DbUpdateConcurrencyException)
    {
        context.Dispose();
        context = new DBContext();
        Entity entity = context.Set<Entity>().Find(entityFromOldContext.Id);

        entity.Property1 = entityFromOldContext.Property1;
        entity.Property2 += 4;

        context.commit();
    }

エンティティでは、次のように同時実行を制御するために追加のプロパティを使用します。

[Timestamp]
public Byte[] RowVersion { get; set; }

これはおそらくエレガントな方法ではありません (そして UnitOfWork パターンを壊します) が、状況によっては役立つかもしれません。

于 2013-05-08T17:54:37.487 に答える