我正在开发ASP.NET MVC,C#和LINQ to SQL中的三明治订购应用程序。该应用程序围绕用户从各种成分创建多个定制三明治。
在确认订单时,我需要知道,在我提交数据库之前,每个成分中有足够的部分用于满足用户订单中的所有三明治,因为添加之间成分可能会缺货它到他们的篮子并确认订单。
关于数据库:
成分 - 存储成分细节,包括部分数量
订单 - 订单的表头,只需存储订单时间
OrderDetail - 在订单中存储每个三明治的记录
OrderDetailItem - 按顺序存储每个三明治中的每种成分
所以基本上我想知道在向Order,OrderDetail和OrderDetailItem添加记录之前确保最佳方法是什么,我可以确保订单得到满足。
答案 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