다음 시나리오는 꽤 일반적이라고 말하지만 해결 방법은 하나 있지만 우아함이 부족합니다.NHibernate 업데이트 전에 dB에 대한 유효성 검사를 수행하는 방법
내가 제공하는 예제는 https://github.com/sharparchitecture/Sharp-Architecture-Cookbook을 기반으로합니다.
코딩중인 응용 프로그램은 ASP.NET MVC 응용 프로그램이며 같은 개체에서 작업하는 여러 사용자를 지원해야합니다.
다음 시나리오는 딱딱한 케이스이지만 올바른 것입니다.
동일한 개체에서 작업하는 두 명의 사용자가 있고 dB 행을 업데이트 할 수 있는지 여부는 특정 필드의 값에 따라 다릅니다. 보다 구체적으로 말하자면, 제품이 있고 단순하게 유지한다고 가정 할 때이 제품에는 "이름"과 "QuantityInStock"필드가 있습니다.
처음에는 제품 및 사용자 1이 10 개 있고 사용자 1과 사용자 2가이 제품을 구매하려고합니다. 두 사용자 모두 초기 양식을 제출하면 재고가 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
}
}
, 내가 전화 한 사실 :
:this.productModelRepository.SaveOrUpdate(productModel);
이 예외가 발생합니다 :
var currentProductModel = Get(productModel.Id);
난 그냥이 작업을 수행하는 경우 있음을 의미
동일한 식별자 값을 가진 다른 객체가 이미 세션 : 1
따라서 모든 값을 productModel에서 currentProductModel로 복사해야합니다. Automapper와 같은 것을 사용할 때도 괜찮지 만, 여전히 한 종류의 객체에서 다른 객체로 데이터를 전송하지 않고도 productModel을 그대로 저장할 수 있어야한다는 느낌으로 나에게 잘못된 느낌을줍니다.
또한 동일한 유효성 검사를 두 번 수행하면 DataAnnotation을 사용한 후 한 번만 업데이트하기 직전에 DRY 원칙이 위반됩니다.
중요한 점은 트릭을 놓치고있는 것 같지만 시작점과 조사 대상을 잘 모르는 것입니다.
이것은 나에게있어 간단한 문제이지만 멋진 해결책을 제시하는 것은 다른 것입니다. 그래서 문제는 과거에이 단순한 사건을 어떻게 다루었습니까? 나는 이것을 overthinking인가?
예 이것은 물론 작동 거래의 직렬화를 보장. 그러나 시나리오는 User1이 5를 사며 User2가 1을 구입하고이 경우 StaleObjectException을 트리거하지 않을 수도 있습니다. – DavidS
왜 staleobject를 트리거하지 않으면 DB에 수량 5 또는 9가 있지만 실제로 4일까요? – Firo
"CreateOrUpdate"에 대한 코드가 명확하지 않을 수 있습니다. 업데이트를 적용하려면 "if"조건의 업데이트를 참조하십시오. 많은 수의 거래가있는 웹 사이트를 상상해보십시오. 재고가있는 상품이 있지만 StaleObjectException이 발생하면 사용자는 주문을 다시 제출하기가 쉽지 않습니다. – DavidS