40 Konflikte behandeln
Konflikte sind das Grauen aller Softwareentwickler. Sie treten auch in unserem Alltag auf, obwohl wir diese Situationen nicht unbedingt als Konflikt ansehen. Nehmen wir beispielsweise an, Sie möchten über das Internet eine Reise buchen und haben bereits eine passende bei einem Anbieter gefunden. Allerdings vergeht eine mehr oder weniger lange Zeit zwischen dem Finden der Reise und Ihrer Entscheidung, diese zu buchen. Nun könnte es bei dem Versuch der Buchung passieren, dass ein anderer Interessent Ihnen die gewählte Reise regelrecht vor der Nase weggeschnappt hat. Das war, im Datenbankjargon, ein Konflikt, der allerdings nicht von der Software behandelt werden muss und schlicht und ergreifend der Rubrik »Pech gehabt« zugeordnet werden kann.
Konflikte treten immer dann auf, wenn in verbindungslosen Umgebungen mit Daten gearbeitet wird. Das Entity Framework gehört dazu. In diesem Kapitel wollen wir uns mit der Behandlung von Konflikten innerhalb des ADO.NET Entity Frameworks beschäftigen und erläutern, welche Möglichkeiten wir beim Auftreten von Konflikten haben, um auf diese zu reagieren.
40.1 Allgemeine Betrachtungen

Was ist überhaupt ein Konflikt? Stellen wir uns zur Beantwortung dieser Frage das folgende Szenario vor. In einem Unternehmen arbeiten mehrere Mitarbeiter mit einer Software, die auf eine Datenbank zugreift. Die Mitarbeiter sollen die Datenbank pflegen, also bestehende Datensätze ändern und ergänzen, andere löschen. Nicht selten kann es dabei vorkommen, dass ein Mitarbeiter des Unternehmens, nennen wir ihn einfach User1, denselben Datensatz wie User2 bearbeitet. Wenn User2 seine Änderungen in der Datenbank speichert, bevor User1 seine eigenen Änderungen zurückschreibt, wie soll die Anwendung reagieren? Sollen die Änderungen von User2 durch die Änderungen von User1 überschrieben, also ersetzt werden? Oder soll eine Ausnahme User1 darauf aufmerksam machen, dass ein anderer Kollege dieselbe Datenzeile bereits editiert hat?
Die Problematik dürfte grundsätzlich klar sein, ist aber auch nicht neu. Das führte in der Vergangenheit dazu, dass zwei Sperrstrategien entwickelt worden sind:
- optimistische Sperren
- pessimistische Sperren
Lassen Sie uns diese beiden Strategien etwas näher betrachten.
40.1.1 Das pessimistische Sperren

Wenn man sichergehen will, dass eine Änderung nicht zu einem Konflikt führt, ist das exklusive physikalische Sperren der Daten in der Datenbank der sicherste Weg. Solange die Daten bedingt durch ein Änderung gesperrt sind, können andere Benutzer nicht schreibend – und in manchen Fällen auch nicht lesend – darauf zugreifen. Niemand kann die Daten ändern, bis die Sperre aufgehoben wird. Dieses Verhalten wird als pessimistisches Sperren bezeichnet.
Der Vorteil des pessimistischen Sperrens ist der garantiert exklusive und problemlose Zugriff eines Users auf Daten. Andererseits werden durch pessimistisches Sperren andere Probleme auftreten, wie beispielsweise eine schlechtere Performance und eine schlechte Skalierbarkeit. Möchte ein anderer User auf gesperrte Daten zugreifen, ist er darauf angewiesen, dass der Benutzer, der die Sperre verursacht hat, möglichst schnell die Sperre wieder aufhebt – die Produktivität sinkt. Stellt man sich zudem vor, dass viele Benutzer gleichzeitig auf die Daten zugreifen wollen, stellt das pessimistische Sperren wegen der schlechten Verfügbarkeit der Daten einen völlig indiskutablen Lösungsansatz dar.
40.1.2 Das optimistische Sperren
Pessimistisches Sperren hat Vor- und Nachteile. Oftmals wiegen die Nachteile stärker als die Vorteile. Das optimistische Sperren, ein gänzlich anderer Lösungsansatz, geht die Problematik anders an: Dabei spielt die Idee, dass der gleichzeitige schreibende Datenzugriff nicht sehr häufig auftritt, die tragende Rolle. Werden Daten nicht sehr häufig geändert und ist die Wahrscheinlichkeit, dass dieselben Daten quasi parallel geändert werden, nicht sehr hoch, dann müssen die Daten tatsächlich nur in dem Moment gesperrt werden, wenn der schreibende Zugriff erfolgt.
Optimistische Sperren erhöhen die Produktivität durch Verbesserung der Performance einer Anwendung, da allen Benutzern gleichermaßen das Recht eingeräumt wird, Daten zu lesen und zu ändern. Allerdings muss beim Zurückschreiben geänderter Daten geprüft werden, ob sich der Datensatz seit dem Lesevorgang verändert hat. Die beste Lösung ist in solchen Fällen, eine Spalte zu einer Tabelle hinzuzufügen, deren Wert sich mit jeder Änderung an der Datenzeile ebenfalls ändert und somit gewissermaßen eine Art Versionierung darstellt. In einer Umgebung mit mehreren Benutzern wird der erste Benutzer seine Änderung problemlos in die Datenbank schreiben können, alle anderen danach werden bei dem Versuch scheitern.
Der SQL Server verwendet für die Versionierung Timestamp-Spalten (bzw. RowVersion-Spalten), deren Wert sich bei jedem Einfüge- oder Aktualisierungsvorgang automatisch verändert. Um festzustellen, ob sich seit dem Lesevorgang eine Datenzeile geändert hat, muss der Wert der Timestamp-Spalte, der beim Lesen der Datenzeile aktuell war, zusammen mit dem Primärschlüssel in die WHERE-Klausel aufgenommen werden, z. B.:
UPDATE ... SET ... WHERE ID = ... AND VersionColumn = ...
Kann die Datenzeile nicht aktualisiert werden, weil sich in der Zwischenzeit der Wert der Timestamp-Spalte geändert hat, liegt ein Parallelitätskonflikt vor.
Nicht jede Tabelle hat eine Timestamp-Spalte. In solchen Fällen bleibt nichts anderes übrig, als die Spalten, die als konfliktverursachend angesehen werden, in die WHERE-Klausel mit aufzunehmen.
Optimistisches Sperren sichert einer Anwendung hohe Verfügbarkeit und Skalierbarkeit. Allerdings kaufen wir uns diese Vorteile nur durch einen höheren Programmieraufwand ein, da wir bei einem auftretenden Konflikt in der Regel darauf reagieren müssen, weil beispielsweise die neuen aktuellen Daten aus der Datenbank gelesen werden müssen.
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.