次のシナリオは、非常に一般的であり、それを解決する方法は 1 つ知っていますが、洗練されていません。
私が提供している例は、 https://github.com/sharparchitecture/Sharp-Architecture-Cookbookに基づいています。
私がコーディングしているアプリケーションは ASP.NET MVC アプリケーションであり、同じオブジェクトで作業する複数のユーザーをサポートする必要があります。
次のシナリオはエッジ ケースですが、有効なシナリオです。
同じオブジェクトで作業している 2 人のユーザーがいて、dB 行を更新できるかどうかは、特定のフィールドの値に依存するとします。より具体的にするために、製品があり、物事を単純にするために、この製品には「Name」フィールドと「QuantityInStock」フィールドがあるとします。
最初に、Product のアイテムが 10 個あり、User1 と User2 がこの製品を購入したいとします。両方のユーザーに最初のフォームが表示されると、これらのアイテムの在庫が 10 個あることが通知されます。ここで、User1 は 10 品目すべてを購入し、User2 はコーヒーを飲みに行きます。したがって、User1 のトランザクションは問題なく実行されます。
その後、User2 は、まだ 10 個のアイテムが在庫にあると考えて、コーヒーを飲んだ後に戻ってきました。そこで彼は 1 を買おうとしましたが、商品の在庫がないため、それを阻止しなければなりません。
したがって、この問題は ASP.NET DataAnnotations 検証を使用することで解決でき、これによりほとんどのケースがキャッチされます。ただし、このエッジ ケースでは、User1 と User2 は同じ操作を実行しますが、User2 がフォームを送信すると ASP.NET 検証に合格しますが、永続化レイヤーに到達するまでに数分の 1 秒以内に実行するとします。 QuantityInStock は 0 です。
これに対する解決策は、可能な限り最新の時点、つまり Update メソッドを呼び出す直前に検証を実行することです。
次に、いくつかのコードについて説明します。
public ProductModel CreateOrUpdate(ProductModel productModel)
{
var currentProductModel = Get(productModel.Id);
var currentQuantityInStock = currentProductModel.QuantityInStock;
if(currentProductModel.QuantityInStock !=0 && productModel.QuantityInStock >= currentQuantityInStock )
{
currentProductModel.QuantityInStock= productModel.QuantityInStock;
currentProductModel.Name = productModel.Name;
this.productModelRepository.SaveOrUpdate( currentProductModel );
return productModel;
}
else
{
//Raise an exception
}
}
今、私が呼んでいるという事実:
var currentProductModel = Get(productModel.Id);
つまり、これを行うだけの場合:
this.productModelRepository.SaveOrUpdate( productModel );
例外が発生します:
同じ識別子値を持つ別のオブジェクトが、すでにセッションに関連付けられています: 1
したがって、すべての値を productModel から currentProductModel にコピーする必要があります。Automapper のようなものを使用する場合は問題ありませんが、あるオブジェクトから別のオブジェクトにデータを転送することなく、productModel をそのまま保存できるはずだと感じるという意味で、私にはまだ少し気分が悪いです。
さらに、1 回は DataAnnotation を使用し、もう 1 回は更新の直前に、同じ検証を 2 回行う必要があるため、DRY 原則に違反します。
要点は、トリックを見逃しているように感じますが、どこから始めて何を調査すればよいかよくわかりません。
私にとってこれは単純な問題ですが、素敵でエレガントな解決策を考え出すことは別のことです。問題は、過去にこの単純なケースにどのように対処したかです。私はこれを考えすぎていますか?