Nous avons un site Web de commerce électronique où les gens peuvent acheter une carte-cadeau. Ces cartes sont stockées dans une table et commandées par un nombre entier à des fins logistiques. Si quelqu'un achète une carte-cadeau, nous insérons un bon de commande dans la base de données et modifions un champ de la première carte éligible afin de savoir qu'elle n'est plus disponible.Verrouiller la table pour lire
Mais parfois, lorsque 2 utilisateurs achètent une carte en même temps, la même carte est donnée pour les deux. Nous avons donc fait une transaction avec IsolationLevel.ReadCommitted
qui ne fonctionne pas. Pour 4 clics simultanés, il y a 1 même Card
pour 2 PurchaseOrder
et un autre Card
pour 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;
}
commentaire rapide: Dans la transaction, nous obtenons les inséré précédemment PurchaseOrder
, modifier son état, puis sélectionnez la carte-cadeau disponible (s), modifier certaines propriétés, SaveChanges()
et retourner la carte-cadeau (s) pour relier au PurchaseOrderLine
. Mais nous ne verrons évidemment pas la sélection de la carte. Comment pourrions-nous faire cela?
Mise à jour:
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;
}
Cette fois j'ai essayé avec IsolationLevel.RepeatableRead
, un Card
n'est plus attribué à 2 PurchaseOrder
. Mais aucun Card
sont retournés de AssignCards()
. Pour 4 clics simultanés, il y a 2 PurchaseOrder
avec 1 distinct Card
et 2 PurchaseOrder
sans Card
.
Que fait AssignCards()? Pouvez-vous ajouter du code de cette méthode? – MikkaRin
Peut-être que vous pouvez créer une solution avec une séquence de base de données, car la base de données prendra soin de ne pas avoir un numéro déjà utilisé ... – DatRid
Quelle plate-forme de base de données utilisez-vous? – mjwills