2016-08-20 11 views
0

私は、バスケットにアイテムを追加できるエンドポイント(ASP.NET WebAPI + Entity Framework 6)を持っています。それは次のようになります。バスケットItem with TransactionScope.ReadCommittedまだ複製を作成中

public int AddToBasket(BasketUpdate update) 
    { 
     var transactionOptions = new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }; 
     using (var scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions)) 
     { 
      var existingBasketItem = basketItems.Query().FirstOrDefault(item => 
        item.UserId == update.UserId 
        && item.AccountId == update.AccountId 
        && item.ProductId == update.ProductId); 
  existingBasketItem = existingBasketItem ?? basketItems.Create(); 
      existingBasketItem.Quantity += update.Quantity; 
      existingBasketItem.AccountId = update.AccountId; 
      existingBasketItem.UserId = update.UserId; 
      existingBasketItem.ProductId = update.ProductId; 

      unitOfWork.Commit(); 

      scope.Complete(); 

      return existingBasketItem.Quantity; 
     } 
    } 

だから、私はこのエンドポイントへの複数の呼び出しを発射すれば、私は常に合算データベース内の1つのエントリで終わることを(私の無限の降誕に)仮定しましたすべての呼び出しの量が正しくこのエンドポイントをFiddlerに浸透させることは、すべての要求が前回の処理が完了するまで待っていることを確認しているようです。すぐに私が探して停止(または他の誰かがバスケットに項目を追加します)しかし

、私はそのような何かを持っ終わる:

Id Quantity ProductId UserId AccountId 
429 12  4560   56 2234 
430 1  4560   56 2234 

それがどのように地球上で起こることができますか?何らかの点でIISサーバー上に2つのインスタンスが存続する可能性がありますか、ここでのトランザクションについて何か誤解していますか?私の髪を引っ張っているので、助けていただければ幸いです。

答えて

0

この方法はまったく機能しません。十分にそれを解決するためのEntityFrameworkアプローチはないようです。 「シリアライザブル」レベルでさえ、選択されたデータをロックするだけで、新しい行が挿入され、いくつかの行に分割された数量を処理するサービスコードが必要になります。

私は、テーブルとスピードの排他的な読み書きを提供するTABLOCKを使用してMERGEを使用してストアドプロシージャを作成しました。

ALTER PROCEDURE [dbo].[UpdateSalesQuantity] 
@AccountId   INT, 
@ProductId   INT, 
@Quantity   INT, 
@AddNotSetQuantity BIT 
AS 
BEGIN 
SET NOCOUNT ON; 

MERGE INTO dbo.BasketItem WITH (TABLOCK) AS target 
USING (Select @AccountId AccountId, @ProductId ProductId) AS source 
ON 
    target.AccountId = source.AccountId 
    AND target.ProductId = source.ProductId 
WHEN MATCHED AND (@AddNotSetQuantity = 0 AND @Quantity > 0) OR (@AddNotSetQuantity = 1 AND target.Quantity + @Quantity > 0) 
    THEN UPDATE SET target.Quantity = (CASE @AddNotSetQuantity WHEN 0 THEN 0 ELSE target.Quantity END) + @Quantity 
WHEN MATCHED AND (@AddNotSetQuantity = 0 AND @Quantity <= 0) OR (@AddNotSetQuantity = 1 AND target.Quantity + @Quantity <= 0) 
    THEN DELETE 
WHEN NOT MATCHED BY TARGET AND @Quantity > 0 
    THEN INSERT (ProductId, AccountId, CreationTime, ModificationTime, [Guid], Quantity) 
     VALUES (@ProductId, @AccountId, GETDATE(), GETDATE(), NEWID(), @Quantity); 

SELECT Quantity FROM dbo.BasketItem WHERE AccountId = @AccountId And ProductId = @ProductId 
END 
関連する問題