UPDATE (2010-12-21): Diese Frage wurde aufgrund von Tests, die ich gemacht habe, komplett neu geschrieben. Auch das war früher eine POCO-spezifische Frage, aber es stellt sich heraus, dass meine Frage nicht unbedingt POCO-spezifisch ist.OptimisticConcurrencyException funktioniert in bestimmten Situationen nicht im Entitätsframework
Ich benutze Entity Framework und ich habe eine Timestamp-Spalte in meiner Datenbanktabelle, die verwendet werden sollte, um Änderungen für optimistische Parallelität zu verfolgen. Ich habe den Gleichzeitigkeitsmodus für diese Eigenschaft im Entity Designer auf "Fixed" gesetzt und bekomme inkonsistente Ergebnisse. Im Folgenden finden Sie einige vereinfachte Szenarien, die zeigen, dass die Parallelitätsprüfung in einem Szenario, jedoch nicht in einem anderen Szenario funktioniert.
Erfolgreich wirft OptimisticConcurrencyException:
Wenn ich eine getrennte Einheit anschließen, dann wird Savechanges eine OptimisticConcurrencyException werfen, wenn es einen Konflikt Zeitstempel:
[HttpPost]
public ActionResult Index(Person person) {
_context.People.Attach(person);
var state = _context.ObjectStateManager.GetObjectStateEntry(person);
state.ChangeState(System.Data.EntityState.Modified);
_context.SaveChanges();
return RedirectToAction("Index");
}
Nicht werfen OptimisticConcurrencyException:
Auf der anderen Seite, wenn ich eine neue Kopie meiner Entität aus dem d ATENBANK und ich auf einigen Gebieten eine teilweise Aktualisierung tun, und dann Savechanges() aufrufen, dann, obwohl es ein Zeitstempel Konflikt ist, verstehe ich nicht ein OptimisticConcurrencyException:
[HttpPost]
public ActionResult Index(Person person) {
var currentPerson = _context.People.Where(x => x.Id == person.Id).First();
currentPerson.Name = person.Name;
// currentPerson.VerColm == [0,0,0,0,0,0,15,167]
// person.VerColm == [0,0,0,0,0,0,15,166]
currentPerson.VerColm = person.VerColm;
// in POCO, currentPerson.VerColm == [0,0,0,0,0,0,15,166]
// in non-POCO, currentPerson.VerColm doesn't change and is still [0,0,0,0,0,0,15,167]
_context.SaveChanges();
return RedirectToAction("Index");
}
Basierend auf SQL Profiler, es sieht aus wie Entity Framework ignoriert die neue VerColm (die Timestamp-Eigenschaft) und verwendet stattdessen die ursprünglich geladene VerColm. Aus diesem Grund wird niemals eine OptimisticConcurrencyException ausgelöst.
UPDATE: Hinzufügen von zusätzlichen Informationen pro Jans Anfrage:
Bitte beachte, dass ich auch Kommentare zu den obigen Code hinzugefügt übereinstimmen mit dem, was ich in meinem Controller-Aktion zu sehen, während er durch dieses Beispiel arbeiten.
Dies ist der Wert des VerColm in der Datenbank vor der Aktualisierung: 0x0000000000000FA7
Hier ist, was SQL Profiler zeigt, wenn das Update durchführen:
exec sp_executesql N'update [dbo].[People]
set [Name] = @0
where (([Id] = @1) and ([VerColm] = @2))
select [VerColm]
from [dbo].[People]
where @@ROWCOUNT > 0 and [Id] = @1',N'@0 nvarchar(50),@1 int,@2 binary(8)',@0=N'hello',@1=1,@2=0x0000000000000FA7
Beachten Sie, dass @ 2 sollte 0x0000000000000FA6 gewesen sein , aber es ist 0x0000000000000FA7
Hier ist die VerColm in meiner Datenbank nach dem Update: 0x0000000000000FA8
Weiß jemand, wie ich dieses Problem umgehen kann? Ich möchte, dass Entity Framework eine Ausnahme auslöst, wenn ich eine vorhandene Entität aktualisiere und es einen Zeitstempelkonflikt gibt.
Dank
Bitte geben Sie den Code ein, der die Speicherung durchführt. –
Ich kann das nicht reproduzieren. Ich erhalte eine OptimisticConcurrencyException, wenn ich versuche, die geladene und geänderte Entität mit einem Timestamp-Konflikt zu speichern. Sind Sie sicher, dass Sie einen Timestamp-Konflikt haben? Können Sie bitte Ihre profilierte SQL-Abfrage posten? – Jan
Hallo Jan, ich habe oben auf Ihre Anfrage zusätzliche Informationen hinzugefügt. –