Atomar einen Zähler Aufrechterhaltung Verwendung Sub-Sonic Active
-
26-09-2019 - |
Frage
Ich versuche, herauszufinden, die richtige Art und Weise zu atomar einen Zähler in einer Tabelle erhöht und die Verwendung diesen Wert erhöht als Pseudo-Display-only-ID für einen Datensatz in einem anderen.
Was ich habe, ist ein Unternehmen, Tisch und ein Arbeitsplatz Tisch. Ich möchte jedes Unternehmen seinen eigenen Satz von job_numbers haben. Ich habe eine Autoinkrement job_id haben, aber diese Zahlen sind für alle Unternehmen geteilt. dh: die Auftragsnummern sollten lückenlos für jedes Unternehmen im Allgemeinen erhöhen
.ie:
- Unternehmen (company_id, next_job_number)
- Jobs (company_id, job_id, job_number)
Zur Zeit dies ich tue (als Methode auf dem Teiljobklasse):
public void SaveJob()
{
using (var scope = new System.Transactions.TransactionScope())
{
if (job_id == 0)
{
_db.Update<company>()
.SetExpression("next_job_number").EqualTo("next_job_number+1")
.Where<company>(x => x.company_id == company_id)
.Execute();
company c = _db.companies.SingleOrDefault(x => x.company_id == company_id);
job_number = c.next_job_number;
}
// Save the job
this.Save();
scope.Complete();
}
}
Es scheint zu funktionieren, aber ich bin mir nicht sicher, ob es hier Gefahren? Es fühlt sich einfach falsch, aber ich bin nicht sicher, wie ich es anders zu tun.
Jede Beratung sehr geschätzt.
Lösung
Zuerst
sollten Sie die Transaction in Verbindung mit einem SharedDbConnectionScope verwenden oder Ihrer Transaktion wird nicht funktionieren wie erwartet.
Zweitens
würde ich einen anderen Ansatz mit einer einzigen Anweisung und ohne die Notwendigkeit, die job_id mit der Firma speichern)
-
Speichern Sie die Aufzeichnung mit job_number = 0
-
Aktualisieren Sie den Datensatz mit so etwas wie dieses
UPDATE JOBS SET JOB_NUMBER = (SELECT MAX (job_number) +1 FROM JOBS WHERE company_id = 12345) WHERE job_id = "+ this.job_id;
(Sie müssen nur diese Abfrage Unterschall Syntax konvertieren, benutze ich Subsonic3 nicht) Das sollte garantieren, dass die Auftragsnummer für jedes Unternehmen einzigartig ist (wenn Sie sowohl das Speichern und Update-Befehl in einer Transaktion wickeln und eine Tabellensperre verwenden).
Andere Tipps
dynamischen Code Mit dem aktuellen höchsten Wert bekommen kann riskant (potenzieller doppelte Wert) wird auf einem hohes Volumen Multi-User-System.
Ein weiterer Ansatz könnte sein, eine neue Tabelle mit zwei Spalten zu erstellen; ein ein Zeichen PK und die andere eine ganze Zahl des letzten relevanten Wert zu speichern. Jedes Mal, wenn Sie einen neuen Wert wollen, erhöhen Sie den Wert in dem Datensatz für das betreffende Unternehmen und verwenden diesen Wert für Ihre Auftragsnummer. Der Charakter PK würde umfasst so etwas wie:
"LAST_ORDER_NUMBER_COMPANY_" + company_id
Ich habe eine gespeicherte Prozedur aufrufen, die entweder automatisch einen neuen Rekord startet das erste Mal, wenn ein Unternehmen einen Auftrag hat, oder Inkrementen es für Folgeaufträge, und gibt die neue Bestellnummer Wert zurück.