transactions - mejorado - google analytics ecommerce appspot
Gestión de artÃculos de eCommerce (1)
Estoy creando una aplicación que vende boletos, tengo una mesa para boletos disponibles
id | serial | sold
-------------------------------
1 | 000001 | false
2 | 000002 | false
3 | 000003 | true
Cuando un usuario solicita un ticket, la aplicación selecciona un ticket y lo marca como vendido.
Mi pregunta es: ¿cómo administrar esta tabla y evitar vender el mismo boleto a un usuario diferente sabiendo que habrá cientos de solicitudes al mismo tiempo?
Estoy pensando en bloquear, pero cuando la fila está bloqueada para una transacción, si otra transacción solicita el bloqueo, debe esperar hasta que la primera transacción finalice y actualizar la fila como se vendió, entonces la segunda transacción devolverá que el ticket se ha vendido. . Ahora, ¿cómo puedo redirigir la segunda transacción a una fila diferente si la fila está bloqueada?
Editar
De acuerdo con el comentario de Paul Zahra, creé un procedimiento almacenado
DECLARE @id varchar(MAX)
SELECT @id = (
SELECT top(1) [Id]
FROM [dbo].[AvailableItems] WITH (ROWLOCK, UPDLOCK)
WHERE ([Sold] = 0) )
UPDATE [dbo].[AvailableItems]
SET [Sold] = 1
WHERE [Id] = @id
SELECT [Id], [Serial], [CreateDate], [AvailableTo]
FROM [dbo].[AvailableItems]
WHERE ([Id] = @id)
Pero necesito estar seguro de qué va a pasar con la segunda transacción si llegan dos transacciones al mismo tiempo. saltará esta fila y pasará a la siguiente fila? o espere a que termine la primera transacción y luego seleccione la misma fila?
Me gustaría bloquear el elemento con un objeto simple y asegurarme de que sea privado / estático. Esto permitirá que su estado se comparta entre todas las instancias de la clase mientras se evita que el objeto se modifique desde fuera de la clase.
Para manipulación de errores y bloqueos, consulte
En C # ¿cómo puedo salir con seguridad de un bloqueo con un bloque try catch dentro?
en apoyo de // El bloqueo de excepción de registro se lanzará automáticamente.
El código no ha sido probado, pero debería darle un buen comienzo.
public class NextTicketinSequence
{
private static int _LastTicketNumber;
private static object _TicketLock;
public static NextTicketinSequence()
{
NextTicketinSequence._LastTicketNumber = 0;
}
public static int GetNextTicketNumber()
{
int ticketId = 0;
try
{
lock(_TicketLock)
{
NextTicketinSequence.LoadLastTicketSold();
ticketId = NextTicketinSequence._LastTicketNumber + 1;
}
}
Catch(Exception ex)
{
//Log exception lock will be released automaticaly
}
return ticketId
}
public static void LoadLastTicketSold
{
//Code to get the last ticket marked as sold
}
}