Optimistisches Sperren
Eintrag zuletzt aktualisiert am: 07.04.2017
Optimistisches Sperren ist ein Verfahren, mit dem Datenzugriffstechniken feststellen, ob ein Datensatz mittlerweile von einem anderen Prozess geändert wurde.
Optimistisches Sperren ist ein Euphemismus, denn tatsächlich wird dabei im
Datenbankmanagementsystem und im RAM nichts gesperrt. Es wird lediglich dafür gesorgt, dass Änderungskonflikte nachträglich auffallen. Der erste Prozess, der eine Änderung schreiben will, gewinnt. Und alle weiteren
Prozesse können nicht schreiben und bekommen eine Fehlermeldung. Um dies zu erreichen werden bei UPDATE- und DELETE-Befehlen in die WHERE-Bedingung einzelne oder mehrere Werte aus dem Ursprungsdatensatz aufgenommen.
Anwendungen des Optimistisches Sperren in .NET
- Command Builder für das DataSet in ADO.NET
- Entity Framework: ConcurrencyCheckAttribute auf Entitätsklassenproperties bzw. Eigenschaft Concurreny Mode = Fixed im EDMX-Designer
Beispiel
Das
DataSet in Verbindung mit dem
DataAdapter und einem
CommandBuilder-
Objekt fragt dazu in der WHERE-Bedingung eines UPDATE- oder DELETE-Befehls nicht nur den oder die Primärschlüsselspalten ab, sondern alle Spalten mit ihrem alten Wert aus der Sicht des aktuellen
Prozesses, also den Werten, die der Prozess beim Lesen des Datensatzes erhalten hat (siehe Listing 1). Wenn zwischenzeitlich ein anderer Prozess einzelne Spalten geändert hat, führt der UPDATE- oder DELETE-Befehl zwar nicht zu einem Laufzeitfehler im
Datenbankmanagementsystem, aber zum Ergebnis, dass „0“ Datensätze betroffen waren. Daran kann der Datenadapter erkennen, dass es einen Änderungskonflikt gab.
UPDATE [dbo].[Flug]
SET [FlugNr] = @p1, [Abflugort] = @p2, [Bestreikt] = @p3, [
CopilotId] = @p4, [FlugDatum] = @p5, [Fluggesellschaft] = @p6, [FlugzeugTypID] = @p7, [FreiePlaetze] = @p8, [LetzteAenderung] = @p9, [Memo] = @p10, [NichtRaucherFlug] = @p11, [PilotId] = @p12, [Plaetze] = @p13, [Preis] = @p14, [Timestamp] = @p15, [Zielort] = @p16
WHERE (([FlugNr] = @p17) AND ((@p18 = 1 AND [Abflugort] IS NULL) OR ([Abflugort] = @p19)) AND ((@p20 = 1 AND [Bestreikt] IS NULL) OR ([Bestreikt] = @p21)) AND ((@p22 = 1 AND [
CopilotId] IS NULL) OR ([
CopilotId] = @p23)) AND ([FlugDatum] = @p24) AND ([Fluggesellschaft] = @p25) AND ((@p26 = 1 AND [FlugzeugTypID] IS NULL) OR ([FlugzeugTypID] = @p27)) AND ((@p28 = 1 AND [FreiePlaetze] IS NULL) OR ([FreiePlaetze] = @p29)) AND ([LetzteAenderung] = @p30) AND ((@p31 = 1 AND [NichtRaucherFlug] IS NULL) OR ([NichtRaucherFlug] = @p32)) AND ([PilotId] = @p33) AND ([Plaetze] = @p34) AND ((@p35 = 1 AND [Preis] IS NULL) OR ([Preis] = @p36)) AND ((@p37 = 1 AND [Zielort] IS NULL) OR ([Zielort] = @p38)))
Listing 1: Update-Befehl, wie ihn ein Sql
CommandBuilder für die Tabelle "Flug" mit dem Primärschlüssel "FlugNr" erzeugt.