LINQ to SQL:并发问题

时间:2010-05-24 11:02:56

标签: sql linq concurrency

我正在开发ASP.NET MVC,C#和LINQ to SQL中的三明治订购应用程序。该应用程序围绕用户从各种成分创建多个定制三明治。

在确认订单时,我需要知道,在我提交数据库之前,每个成分中有足够的部分用于满足用户订单中的所有三明治,因为添加之间成分可能会缺货它到他们的篮子并确认订单。

关于数据库:

成分 - 存储成分细节,包括部分数量 订单 - 订单的表头,只需存储订单时间
OrderDetail - 在订单中存储每个三明治的记录
OrderDetailItem - 按顺序存储每个三明治中的每种成分

所以基本上我想知道在向Order,OrderDetail和OrderDetailItem添加记录之前确保最佳方法是什么,我可以确保订单得到满足。

4 个答案:

答案 0 :(得分:2)

    try
    { 
       Begin netTransaction();
        If (IsEnoughIngredients())
        {
           1. Build your sandwich
           2. Add sandwich to data context with a timestamp (or whatever you chose for concurrency checking)
           3. SubmitChangesToDataContext()
           4. CommitNetTransaction() 
        }
    } catch (Exception e)
    {
       Rollback netTransaction();
       InformUser();
    }

答案 1 :(得分:1)

您可以采取的方法数量,但我会做类似下面的伪代码。安全假设通常会有足够的成分来满足订单,因此围绕该假设构建交易控制并处理极少数例外情况。

Begin transaction (Isolation = Repeatable Read)

For Each OrderDetail In Order.OrderDetailCollection
    For Each OrderDetailItem In OrderDetail.OrderDetailItemCollection
        Update Ingredient
        Set Portions = (Portions – OrderDetailItem.Portions)
        Where Ingredient.ID = OrderDetailItem.IngredientID
        And (Portions – OrderDetailItems.Portions) >= 0

        If RecordsAffected != 1 Then
            Rollback Transaction
            SufficientStock = false
            Exit For
        End If
    Next

    If(SufficientStock = false)
        Exit For
    End If
Next

编辑:如果你可以说服你离开LINQing的一切,那么避免圆形跳闸的另一种方法就是下面的内容:

Begin transaction 
    Insert Order (return OrderID)
    Insert OrderDetails
    Insert OrderDetailItems

    Execute  update stock stored procedure (see below)
    If (Success)
        Commit transaction
    Else
        Rollback transaction
    End IF

更新库存程序的代码:

CREATE PROCEDURE dbo.StockLevel_UpdateByOrderID
(
    @OrderID INT
    , @Success BIT
)

SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL REPEATEABLE READ

BEGIN TRANSACTION

DECLARE @IngredientCount INT

-- Determine number of ingredients in whole order
SELECT
    @IngredientCount = COUNT(odi.IngredientID)
FROM
    dbo.OrderDetailItem odi
INNER JOIN
    dbo.OrderDetail od
ON  od.OrderDetailID = odi.OrderDetailID
WHERE
    od.OrderID = 1
GROUP BY
    odi.IngredientID    

-- Update stock levels for all ingredients
UPDATE
    dbo.Ingredient
SET
    Portions = (i.Portions - odi.TotalPortions)
FROM
    dbo.Ingredient i
INNER JOIN
    (
    SELECT
        odi.IngredientID
        , SUM(odi.Portions) AS TotalPortions
    FROM
        dbo.OrderDetailItem odi
    INNER JOIN
        dbo.OrderDetail od
    ON  od.OrderDetailID = odi.OrderDetailID
    WHERE
        od.OrderID = 1
    GROUP BY
        odi.IngredientID
    ) odi
ON  odi.IngredientID = i.IngredientID
WHERE
    (i.Portions - odi.TotalPortions) >= 0

-- Is number of ingredients updated correct?
IF(@@ROWCOUNT != @IngredientCount)
BEGIN
    ROLLBACK TRANSACTION
    SET @Success = 0
END
ELSE
BEGIN
    COMMIT TRANSACTION
    SET @Success = 0
END

答案 2 :(得分:0)

每次存放三明治时,您都应该更新Ingredient数量。

但是,这会阻止其他用户在您提交更改之前使用相同的成分(即使库存足够)。

最好使用在添加每种成分后提交的临时表。这样可以立即显示更改。

当您准备好整体提交订单时,记录只会从登台表移到永久登记表。

但是,您应该自己实施一些ROLLBACK机制来处理过时的记录。例如,一个cron作业将监视订单上的活动并删除那些在10分钟左右没有活动的那些。

答案 3 :(得分:0)

数据库代码很有用,但如果你可以提供帮助,那就不好绑定数据库。 菜单显示应基于观看时的当前成分, 因此,除了成分之外应该是一个罕见的例外,或者你的三明治店不会持续足够长的时间来关心软件的质量。

如何避免成分更新的往返? 链接是否支持配料表上的某种批量插入? cifey