這次目的是模擬客戶搶購商品的狀況,現在很多電商崛起,其中一個很重要的議題在於避免商品超賣,目前想到的方式由一隻Stored Procedure負責控制,當要求的商品數量大於庫存時,回傳結果但不更新商品數量代表下單失敗。所有客戶Transaction下單必須呼叫此Stored Procedure執行。

撰寫一個擁有Buy方法的Customer類別,,new出10幾個物件執行Thread,模擬消費者同時搶購的狀況。

第一次寫Stored Procedure紀錄一下ASP.NET使用Entity Framework呼叫的過程。

使用Entity Framewrok
public int Buy(int productID, int quantity)
{
    int ResultQuantity = -1;
    using (var db = new TestDBEntities())
    {
        Nullable newId = db.SP_QuantityChange_Test(productID, quantity).FirstOrDefault();
        if (newId.HasValue)
        {
            ResultQuantity = newId.Value;
        }
    }         
    return ResultQuantity;
}


由於自己電腦的Entity Framework被我玩到環境怪怪的無法成功(同事的電腦可以成功),只好本機改使用SQL Query嘗試,順便將兩者都記錄下來。

使用SQL Query
public int Buy(int productID, int quantity)
{
    int ResultQuantity = -1;
    using (var db = new TestDBEntities())
    {
        var Params = new SqlParameter[] { new SqlParameter("@productID", productID), new SqlParameter("@quantity", quantity) };
        int result = db.Database.SqlQuery(@"EXEC [dbo].[SP_QuantityChange_Test] @ID = @productID, @Quantity = @quantity", Params).FirstOrDefault();

        ResultQuantity = result;
    }
         
    return ResultQuantity;
}


SQL Server預存程序內容
ALTER PROCEDURE [dbo].[SP_QuantityChange_Test] @ID INT, @Quantity INT
AS
DECLARE
@CurrentQuantity INT,
@ResultQuantity INT
BEGIN TRY
 SELECT @CurrentQuantity = Product_Qty FROM C_Inventory_M WHERE Product_id = @ID
 SET @ResultQuantity = @CurrentQuantity - @Quantity;
  IF ( @ResultQuantity >= 0)
   BEGIN
   UPDATE C_Inventory_M SET Product_Qty = (@ResultQuantity) WHERE Product_id = @ID   
   END
 SELECT CAST(@ResultQuantity as int)
END TRY

BEGIN CATCH
    SELECT CAST(-1 as int)
END CATCH


另外Stored Procedure可以使用SQL DatabaseMenegement Tool逐步執行偵錯,還能使用監看式,以及可使用Try Catch,在執行失敗的時候輸出錯誤訊息存到別的Table。

參考資料:
接收預存程式回傳值:http://stackoverflow.com/questions/14735477/get-return-value-from-stored-procedure
預存程式使用TryCatch:https://technet.microsoft.com/zh-tw/library/ms179296(v=sql.105).aspx

沒有留言:

張貼留言