Ich verwende den folgenden Code in einer ASP.NET-Seite, um einen Datensatz zu erstellen, dann die Datensätze zu zählen, um sicherzustellen, dass ich eine festgelegte Grenze nicht überschritten habe, und die Transaktion zurückzusetzen, wenn dies der Fall ist.
using (var session = NhibernateHelper.OpenSession())
using (var transaction = session.BeginTransaction())
{
session.Lock(mall, LockMode.None);
var voucher = new Voucher();
voucher.FirstName = firstName ?? string.Empty;
voucher.LastName = lastName ?? string.Empty;
voucher.Address = address ?? string.Empty;
voucher.Address2 = address2 ?? string.Empty;
voucher.City = city ?? string.Empty;
voucher.State = state ?? string.Empty;
voucher.Zip = zip ?? string.Empty;
voucher.Email = email ?? string.Empty;
voucher.Mall = mall;
session.Save(voucher);
var issued = session.CreateCriteria<Voucher>()
.Add(Restrictions.Eq("Mall", mall))
.SetProjection(Projections.Count("ID"))
.UniqueResult<int>();
if (issued >= mall.TotalVouchers)
{
transaction.Rollback();
throw new VoucherLimitException();
}
transaction.Commit();
return voucher;
}
Allerdings bekomme ich eine Menge von Deadlocks. Ich vermute, dass dies geschieht, weil ich versuche, die Datensätze in einer Tabelle zu zählen, in die ich gerade eine Einfügung vorgenommen habe, und eine Sperre noch auf der eingefügten Zeile gehalten wird, was die Blockierung verursacht.
- Kann jemand dies bestätigen?
- Kann jemand eine Lösung vorschlagen?
Ich habe versucht, SetLockMode(LockMode.None) auf die letzte Abfrage aufrufen, aber das führt zu einer NullReferenceException, die ich nicht herausfinden kann.
Bearbeiten: Wenn ich die Abfrage ausführe, bevor ich das Objekt speichere, funktioniert es, aber dann erreiche ich nicht das Ziel, zu überprüfen, dass meine Einfügung nicht irgendwie über das Limit hinausgeht (im Fall von gleichzeitigen Einfügungen).
Bearbeiten: Ich habe festgestellt, dass die Verwendung von IsolationLevel.ReadUncommited im Aufruf session.BeginTransaction das Problem löst, aber ich bin kein Datenbankexperte. Ist dies die geeignete Lösung für das Problem oder sollte ich meine Logik irgendwie anpassen?