1

EntityFrameworkがどのように機能するかを学ぼうとしています。EF SaveChangesは、基本的にトランザクション更新のラッパーであることを理解しています。また、必要に応じて2つのコンテキストをTransactionScopeでラップできることも理解しています。

私はコードファーストアプローチを使用しています。

私が理解していないのは、次のような更新をどのように行うかです。

UPDATE Inventory SET Available = Available - 1 WHERE Available > 0

言い換えると、更新を行う前に、少なくともX個の使用可能な在庫があることを確認するにはどうすればよいですか?

製品の在庫を調べて、購入を完了するのに十分な在庫があることを確認するコードを記述できると思います。

if (Product.Inventory - quantityToPurchase < 0) throw new Exception(..)

しかし、2人の顧客が同時に購入しようとし、各顧客のデータベースからフェッチされたオブジェクトが2つのアイテムを在庫に持っていると主張するシナリオではどうでしょうか。上記の私の論理はそれを捕らえません。

SaveChanges()メソッドがオブジェクトIFにのみ変更をコミットし、IFのみ(Available - quantity)が0より大きいことを確認するにはどうすればよいですか?

4

2 に答える 2

1

SaveChangesメソッドをオーバーライドしてエンティティを保存するときに、このチェックを行う必要があります。

public override int SaveChanges()
{
    var entities = ChangeTracker.Entries()
                                .Where(e => e.State == EntityState.Added || 
                                            e.State == EntityState.Modified)
                                .Select(e => e.Entity())
                                .OfType<YourEntityType();

    foreach (var entity in entities)
    {
        // Run business rule
    }

    return base.SaveChanges();
}
于 2012-06-25T17:45:45.717 に答える
1

Entity Frameworkは、デフォルトでOptimisticConcurrencyを使用します。私が元の投稿で説明したのは、EFの悲観的並行性と呼ばれるものです。これを実現するために使用できる属性は2つあります。

1つ目は、テーブルに列Timestampを作成する方法です。rowversionEFはこれを自動的に検出whereし、エンティティのプロパティの値をデータベースの列の値と比較する句を常に更新に追加します。updateステートメントは、2つが一致する場合にのみ成功します。rowversion列はサーバーによって自動的にインクリメントされます。これにより、メモリ(POCO)にあるのと同じデータを常に更新することができます。フェッチした後、更新する前に他の誰かがその行を変更した場合、更新は失敗します。

2つ目はConcurrencyCheck、と同様に機能するものTimestampです。これにより、POCOプロパティの値がwhere句に含まれるようになります。大きな違いは、意志のようにこの列を更新しないrowversionことです。

于 2012-06-30T03:26:40.757 に答える