【发布时间】:2017-09-22 10:28:25
【问题描述】:
我们有一个电子商务网站,人们可以在其中购买礼品卡。这些卡片存储在一个表中,并按整数排序以用于逻辑目的。如果有人购买了礼品卡,我们会在数据库中插入采购订单并编辑第一张符合条件的卡的字段,以便知道它不再可用。
但有时当 2 位用户同时购买一张卡时,两人都会获得同一张卡。所以我们与IsolationLevel.ReadCommitted 进行了交易,但它不起作用。对于 4 次并发点击,有 1 个相同的 Card 对应 2 个 PurchaseOrder,另一个 Card 对应 2 个 PurchaseOrder。
TransactionOptions transOption = new TransactionOptions();
transOption.IsolationLevel = IsolationLevel.ReadCommitted;
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, transOption))
{
PurchaseOrder purchaseOrder = GetFull(request.OrderId);
purchaseOrder.ChangeTracker.ChangeTrackingEnabled = true;
purchaseOrder.IdStatus = DbConstants.RefPurchaseOrderStatus.Completed;
//select the quantity of purchased gift cards and update them with ObjectContext.SaveChanges()
List<Card> cards = _cardBusiness.AssignCards(purchaseOrder.Quantity, purchaseOrder.IdProduct, purchaseOrder.IdUserAccount, purchaseOrder.IdChannel);
Card[] arrCards = cards.ToArray();
int count = 0;
//Set a link between a PurchaseOrder Line and the Card
foreach(PurchaseOrderLine line in purchaseOrder.PurchaseOrderLines)
{
line.ChangeTracker.ChangeTrackingEnabled = true;
line.IdCard = arrCards[count].Id;
count++;
}
PurchaseOrder po = Update(purchaseOrder);
scope.Complete();
return true;
}
快速评论:在交易中,我们得到之前插入的PurchaseOrder,更改其状态,然后选择可用的礼品卡,编辑一些属性,SaveChanges()并返回礼品卡链接到PurchaseOrderLine。
但我们显然没有锁定卡片选择。我们怎么能这样做?
更新:
public static List<Card> AssignCards(int qty, int idProduct, Guid idUserAccount, int? idChannel)
{
using (RestopolitanEntities context = GetContext())
{
try
{
var Xcards = (from c in context.Cards
select c);
List<Card> cards = Xcards.OrderBy(c => c.IdOrder).Take(qty).ToList();
foreach (Card card in cards)
{
card.ChangeTracker.ChangeTrackingEnabled = true;
card.UseDate = DateTime.Now;
}
context.SaveChanges();
return cards.ToList();
}
catch (Exception ex)
{
HandleException(ex);
}
}
return null;
}
这次我尝试了IsolationLevel.RepeatableRead,一个Card不再归属于2个PurchaseOrder。但是AssignCards() 没有返回Card。对于 4 次并发点击,有 2 个 PurchaseOrder 有 1 个不同的 Card 和 2 个 PurchaseOrder 没有 Card。
【问题讨论】:
-
AssignCards() 是做什么的?可以加一下这个方法的代码吗?
-
也许您可以使用数据库序列创建解决方案,因为数据库会注意您不会获得已使用的数字...
-
您使用的是什么数据库平台?
-
SQL Server 2014 实体框架 6
标签: c# sql entity-framework locking transactionscope