2016-06-13 3 views
0

Ich stieß auf dieses Problem, wenn 2 verschiedene Benutzer meiner Website einen Produktverkauf zur gleichen Zeit erstellten. Dies sollte 2 verschiedene Anfragen an den Server generieren und 2 verschiedene Verkaufstickets drucken. Das Problem ist, dass, wenn die Serveranforderungen zur gleichen Zeit (oder sehr nahe beieinander) eingehen, beide Zweige die gleichen Tickets drucken, anstatt dass sie jeweils ihr eigenes Ticket drucken.Wenn zwei Benutzer auf die gleiche Methode zugreifen, wird das Ergebnis freigegeben

mein Code hier:

Branch   Total CreatedAt    ProductSaleId 
EBQ Centro Maya 35.00 2016-06-13 15:35:54.743 3263825d-bca3-4d18-bbca-3eebe4c3398a 
EBQ PA Chetumal 30.00 2016-06-13 15:35:54.647 01f52d7d-5745-426b-a973-4a701a18b8e4 

Dies sind die Einträge DB, 2 verschiedene Zweige einen jeden Verkauf an 15.35.54.

Also, wenn der Verkauf erfolgt, wird PrintReceipt Methode wie folgt genannt:

HelperObjects.ThermalPOS58.PrinterController.PrintReceipt(new InvoiceReceipt() 
      { 
       Discount = discount, 
       InvoiceNumber = "TEST", 
       SubTotal = decimal.Parse(createProductSale.Total), 
       Total = total, 
       Change = createProductSale.Change ?? "0", 
       ClientAmount = createProductSale.ClientAmount, 
       InvoiceDateFormatted = 
        DateTime.UtcNow.ConvertUtcTimeToTimeZone("", User.Identity.GetUserId()) 
         .ToString("dd/MM/yyyy HH:mm:ss"), 
       BranchName = _unitOfWork.BranchRepository.GetById(branchId).Name, 
       InvoiceItems = invoiceReceipts, 
       PrinterName = _unitOfWork.BranchRepository.GetById(branchId).PrinterName, 
       IsTpv = createProductSale.IsTpv 
      }); 

PrintReceipt Methode sieht wie folgt aus:

private static InvoiceReceipt _mappedInvoice ; 

    public static void PrintReceipt(InvoiceReceipt invoiceReceipt) 
    { 
     _mappedInvoice = invoiceReceipt; 
     var printNodeIntegration = new PrintNodeIntegration(); 
     printNodeIntegration.Print(GetDocument(), invoiceReceipt.PrinterName); 
    } 

Jeder Aufruf seine eigene Rechnung an die PrintReceipt Methode sendet und es funktioniert gut, außer wenn die Verkäufe zur gleichen Zeit gemacht werden. Wenn dies geschieht, drucken beide Zweige den gleichen Beleg. Normalerweise derjenige, der zuerst kam.

Irgendwelche Ideen?

+4

'statische' Mitglieder werden in allen Sitzungen geteilt. Verwenden Sie "Sitzung" oder ermitteln Sie einen anderen Weg, um die Rechnung im Status zu behalten. –

+3

Wo sonst benutzen Sie '_mappedInvoice'? Warum brauchst du überhaupt ein statisches Mitglied? –

+0

Die statische sieht verdächtig, aber sollte dies nicht in dem bereitgestellten Code beeinflussen, es sei denn, es wird in GetDocument() verwendet (große rote Flagge hier, vermute ich); Also, was macht GetDocument() eigentlich? Zeigen Sie den Code für GetDocument() an. Wenn GetDocument() die statische Variable _mappedInvoice verwendet, warum sollte statt "billReceipt" ein static verwendet werden, um GetDocument() zu übergeben? –

Antwort

4

static Mitglieder werden innerhalb des Prozesses geteilt. In ASP.NET wird für alle Sitzungen in einem App-Pool derselbe Prozess verwendet, sodass alle denselben Status static haben.

Die statische Session Eigenschaft trennt Daten von Benutzersitzung, so ist es ein besser Ort sitzungsspezifische Daten zu halten:

Session["mappedInvoice"] = invoiceReceipt; 

Aber es ist unklar, wie Sie es verwenden, wenn es zu wissen, sogar muss in der Sitzung gespeichert werden. Normalerweise verwenden Sie die Sitzung, um Daten zu speichern, die über Anforderungen hinweg bestehen müssen.

+0

Sie haben Recht, ich brauche diese Informationen nicht wirklich in der Sitzung gespeichert, da es nur eine einzige Anfrage ist. Und am wichtigsten klingt das Teilen desselben Zustands genau das Gegenteil von dem, was ich versuche zu tun. Scheint so, als würde es mein Problem lösen, wenn ich es nicht statisch mache. – Benjamin

-1
private static InvoiceReceipt _mappedInvoice ; 
private readonly static Object _lockObject = new Object(); 

public static void PrintReceipt(InvoiceReceipt invoiceReceipt) 
{ 
    Lock(_lockObject) 
    { 
     _mappedInvoice = invoiceReceipt; 
     var printNodeIntegration = new PrintNodeIntegration(); 
     printNodeIntegration.Print(GetDocument(), invoiceReceipt.PrinterName); 
    } 
} 

Dies verhindert, dass Anrufe, die dazwischen kommen, wenn _mappedInvoice gesetzt und .print aus Zurücksetzen _mappedInvoice genannt. Der spätere Anruf wartet, bis der aktuelle Anruf die Sperre aufgibt.

+2

Dies verhindert unnötigerweise, dass diese Operationen parallel ausgeführt werden, wenn es keinen Grund gibt, dass sie nicht parallel ausgeführt werden. – Servy

+0

Es kann einen bestimmten Grund dafür geben, mit einer statischen Methode zu gehen (die Frage wurde nicht anders angegeben). Wenn dies der Fall ist, erklärt diese Antwort, warum sich sein Code wie er verhält und wie er zu beheben ist. Sie können aus den in der ursprünglichen Frage angegebenen Informationen nicht wissen, dass dies nicht der Fall ist. Sie haben angenommen, dass er keine statische Methode benötigt. Ich stimme zu, dass alle Dinge gleich sind, parallele Ausführung wäre besser, wenn es keinen spezifischen Grund für die Verwendung von statischen gibt. – Kevin

+0

Die Frage machte deutlich, dass die fraglichen Daten tatsächlich anforderungsspezifisch sind und sogar * Beispieldaten für jede Anfrage * zeigten. Es ist keine Annahme, dass diese Daten nicht geteilt werden sollten; es ist * ein Teil der expliziten Anforderungen *, dass die Informationen nicht geteilt werden. – Servy

Verwandte Themen