C# 用于读取的锁表
我们有一个电子商务网站,人们可以在那里购买礼品卡。这些卡存储在一个表中,并按整数排序,以便于逻辑操作。如果有人买了一张礼品卡,我们会在数据库中插入一张采购订单,并编辑第一张合格卡的字段,以便知道它不再可用 但有时当两个用户同时购买一张卡时,两个用户都会获得相同的卡。因此,我们使用C# 用于读取的锁表,c#,sql,entity-framework,locking,transactionscope,C#,Sql,Entity Framework,Locking,Transactionscope,我们有一个电子商务网站,人们可以在那里购买礼品卡。这些卡存储在一个表中,并按整数排序,以便于逻辑操作。如果有人买了一张礼品卡,我们会在数据库中插入一张采购订单,并编辑第一张合格卡的字段,以便知道它不再可用 但有时当两个用户同时购买一张卡时,两个用户都会获得相同的卡。因此,我们使用IsolationLevel.ReadCommitted进行了一个事务,但该事务不起作用。对于4次同时单击,2次采购订单有1张相同的卡,2次采购订单有另一张卡 TransactionOptions transOption
IsolationLevel.ReadCommitted
进行了一个事务,但该事务不起作用。对于4次同时单击,2次采购订单
有1张相同的卡
,2次采购订单
有另一张卡
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;
}
这次我尝试了使用
IsolationLevel.RepeatableRead
,一张卡不再归属于2PurchaseOrder
。但是,AssignCards()
没有返回任何Card
。对于4次同时单击,有2次PurchaseOrder
与1张不同的Card
和2次PurchaseOrder
与Card在交易开始时获取应用程序锁
context.Database.ExecuteSqlCommand("exec sp_getapplock 'AssignCards','Exclusive';");
或者在识别要使用的卡的查询上使用一些锁定提示:
var sql = "select top (@qty) CardId from Cards with (rowlock, updlock, readpast) where UseDate is null";
var cardIds = context.Database.SqlQuery<int>(sql,qty).ToList();
List<Card> cards = context.Cards.Where(c => cardIds.Contains(c.CardId)).ToList();
var sql=“从使用日期为空的(rowlock、updlock、readpass)卡片中选择top(@qty)cardd”;
var cardds=context.Database.SqlQuery(sql,qty.ToList();
List cards=context.cards.Where(c=>cardds.Contains(c.cardd)).ToList();
如果使用锁定提示,则可以使用readpass提示允许并发会话跳过被其他会话锁定的卡。如果你使用Apple锁,你可以在事务中间释放锁(在选择卡之后)。< /P>什么是分配卡()?您可以添加此方法的代码吗?也许您可以创建一个具有数据库序列的解决方案,因为db会注意您不会获得已使用的编号…您使用的是什么数据库平台?SQL Server 2014 Entity Framework 6
var sql = "select top (@qty) CardId from Cards with (rowlock, updlock, readpast) where UseDate is null";
var cardIds = context.Database.SqlQuery<int>(sql,qty).ToList();
List<Card> cards = context.Cards.Where(c => cardIds.Contains(c.CardId)).ToList();