Atomic Increment mit Entity Framework
Ich habe einen MySQL Server habe ich Zugriff über Entity Framework 4.0. In der Datenbank habe ich eine Tabelle namens Funktioniert, in die einige zählt. Ich entwickle web-site mit Asp.net. Diese Tabelle acccesable ein Benutzer gleichen Zeit. Und diese situation führt zu falschen incerement problem.
Mein code so:
dbEntities myEntity = new dbEntities();
var currentWork = myEntity.works.Where(xXx => xXx.RID == 208).FirstOrDefault();
Console.WriteLine("Access work");
if (currentWork != null)
{
Console.WriteLine("Access is not null");
currentWork.WordCount += 5;//Default WordCount is 0
Console.WriteLine("Count changed");
myEntity.SaveChanges();
Console.WriteLine("Save changes");
}
Console.WriteLine("Current Count:" + currentWork.WordCount);
Wenn man mehr als Faden auf die Datenbank zugreifen, wird nur die Letzte änderung bleiben.
Aktuellen Ausgabe:
t1: Thread-Eine - t2: Thread Zwei
t1: Zugang arbeiten
t2: Access arbeiten
t2: der Zugang ist nicht null
t1: Zugang ist nicht null
t1: Anzahl geändert
t2: Anzahl geändert
t1: Speichern Sie die änderungen
t2: Speichern Sie die änderungen
t1: Aktuelle Anzahl: 5
t2: Aktuelle Anzahl: 5
Erwartete Ausgabe:
t1: Zugang arbeiten
t2: Access arbeiten
t2: der Zugang ist nicht null
t1: Zugang ist nicht null
t1: Anzahl geändert
t2: Anzahl geändert
t1: Speichern Sie die änderungen
t2: Speichern Sie die änderungen
t1: Aktuelle Anzahl: 5
t2: Aktuelle Anzahl: 10
Weiß ich, warum apeear dieses problem, denn dieser code ist nicht atomar. Wie kann ich schalten atomarer Vorgang?
- Ich weiß, MsSql Sie können Transaktionen haben, können Sie das gleiche tun in MySql? Ich weiß auch, dass
SaveChanges()
ermöglicht einen booleschen Wert, aber ich glaube nicht, dass das hilft in diesem Fall. - können Sie versuchen, diese,
lock (currentWork ) { Console.WriteLine("Access is not null"); currentWork.WordCount += 5;//Default WordCount is 0 Console.WriteLine("Count changed"); myEntity.SaveChanges(); Console.WriteLine("Save changes"); }
es hat eine Weile, da ich habe anständige threading - Oh, und übrigens: ein guter trick. Sie können Ihre
where
Zustand, innen Ihrefirst or default
und entfernen Sie diewhere
komplett. - dieser trick helfen die performance zu verbessern? oder trick kann helfen, besser lesbar-Abfrage?
- Ich denke, es macht es besser lesbar, aber ich bin mir nicht sicher auf die performance. Ich nehme an, es wird
where
für Sie. Nützlich, wenn Sie große Abfragen. - vielleicht ist dies nützlich, stackoverflow.com/a/17972089/1347784
Du musst angemeldet sein, um einen Kommentar abzugeben.
Mit Entity Framework-Sie können nicht machen dies eine "Atomare" operation. Sie haben die Schritte:
Zwischen diesen Schritten kann ein anderer client laden Sie die Entität aus der Datenbank, die hat noch den alten Wert.
Der beste Weg, um mit dieser situation umzugehen, ist die Verwendung vollständige Parallelität. Im Grunde bedeutet es, dass die änderung in Schritt 3 wird nicht gespeichert, wenn der counter ist nicht mehr das gleiche, dass es beim laden der Entität in Schritt 1. Stattdessen erhalten Sie eine Ausnahme, dass Sie behandeln können durch erneutes laden der Entität und einem erneuten Wandel.
Den workflow würde wie folgt Aussehen:
Work
Person dieWordCount
- Eigenschaft müssen so markiert werden, dass eine Parallelität token (Anmerkungen oder Fluent-API im Fall von Code-First)SaveChanges
imtry-catch
block und abfangen von Ausnahmen, die vom TypDbUpdateConcurrencyException
catch
block aus der Datenbank, übernehmen Sie die änderung wieder und rufenSaveChanges
wiederIn diese Antwort finden Sie ein code Beispiel für diese Vorgehensweise (mit
DbContext
).WordCount
zu markieren es als Parallelität token.Nächste Weg wird funktionieren, wenn Sie das hosting Ihrer Website in den einzelnen Prozess(es funktioniert nicht mit web-farm oder web-gardsen):
Was Sie sonst noch tun können, ist, in raw SQL-Abfrage über ObjectContext: