Ich denke, gerade die Problematik lässt sich so lösen.
Eine andere Möglichkeit wäre höchstens, dass der User explizit angibt, dass er mit der Bearbeitung fertig ist, was natürlich automatisch passiert, wenn er Speichern klickt oder "manuell", wenn er Abbrechen klickt.
Die beiden Ansätze lassen sich natürlich kombinieren:
Du benötigst eine Tabelle, in der Du die LOCKs verwaltest:
ID (int), LOCKStart (datetime), LOCKUserID (int), LOCKDatensatzID(int), LastChangeOfDatensatz (datetime), LOCKActive (boolean/enum)
Fälle/Abläufe
- User 1 wählt bestimmten Datensatz zur Bearbeitung.
-> LOCK prüfen, es ist kein LOCK aktiv und restl. Bed. egal.
-> LOCK auf diesen Datensatz setzen, mit UserID/SessionID und Zeitstempel der Anfrage
- User 2 will diesen Datensatz vor [Zeitstempell + x] bearbeiten
-> LOCK prüfen, es ist nicht "kein LOCK" und nicht ein LOCK auf User 2 und LOCK ist nicht abgelaufen.
-> Meldung: "Dieser Datensatz wird von User 1 bearbeitet und steht spätestens um [Zeitstempel + x] wieder zur Bearbeitung zur Verfügung."
- User 2 will diesen Datensatz nach [Zeitstempell + x] bearbeiten
-> LOCK prüfen, es ist nicht "kein LOCK" und nicht ein LOCK auf User 2, aber LOCK ist abgelaufen.
-> eigenen LOCK setzen, LOCK von User 1 inaktiv setzen, User 1 hat es verpennt
- User 1 klickt Abbrechen:
-> LOCK auf inaktiv setzen
- User 1 klickt Speichern vor [Zeitstempel + x]:
-> LOCK prüfen, es ist der LOCK, der in der UserSession gespeichert ist, er ist noch nicht abgelaufen.
-> Speichern, Last-Change-Zeitstempel eintragen, LOCK auf inaktiv setzen
- User 1 klickt Speichern nach [Zeitstempel + x], keiner war in der Zwischenzeit am Datensatz:
-> LOCK prüfen, letzter ist der LOCK, der in der UserSession gespeichert ist, er ist abgelaufen, macht aber nix
-> Speichern, Last-Change-Zeitstempel eintragen, LOCK auf inaktiv setzen
- User 1 klickt Speichern nach [Zeitstempel + x], User 2 hat in der Zwischenzeit den Datensatz geändert:
-> LOCK prüfen, letzter LOCK ist von User 2, der LOCK ist inaktiv
-> LastChange des Datensatz mit LastChange aus dem eigenen LOCK vergleichen. (LastChange > als LastChange im LOCK)
-> Meldung: "Du warst zu langsam, der Datensatz wurde von User 2 geändert", Weiterleitung zur Bearbeitungsausgangsseite -> weiter mit Ablauf 1
- User 1 klickt Speichern nach [Zeitstempel + x], User 2 hat in der Zwischenzeit den Datensatz bearbeiten wollen, aber abgebrochen:
-> LOCK prüfen, letzter LOCK ist von User 2, der LOCK ist inaktiv
-> LastChange des Datensatz mit LastChange aus dem eigenen LOCK vergleichen. (LastChange < als LastChange im LOCK)
-> Speichern, Last-Change-Zeitstempel eintragen, LOCK ist bereits inaktiv
- User 1 klickt Speichern nach [Zeitstempel + x], User 2 hat in der Zwischenzeit angefangen, den Datensatz zu bearbeiten und ist noch dabei (oder hat ohne Abbrechen zu drücken aufgehört):
-> LOCK prüfen, letzter LOCK ist von User 2, der LOCK ist aktiv
-> Meldung: "Du warst zu langsam, User 2 bearbeitet jetzt den Datensatz"
ACHTUNG:
- Die LOCKs werden nicht gelöscht, sondern nur inaktiv gesetzt.
- Es ist eine sinnvolle Größenordnung für x zu finden.
- Jeder der beschriebenen Absätze muss als eine Transaktion ausgeführt werden.
- Weiterhin musst Du Dir überlegen, ob Du dem User nur die Zeit x vom ersten "ich will bearbeiten" bis zum speichern geben willst, oder aber, ob die Anfangszeit des LOCK bei jedem Seitenaufruf (z.B: einer Vorschau) aktualisiert wird. Ich habe oben den ersten Fall beschrieben, da es bei einer Aktualisierung nicht möglich ist, dem User 2 eine sinnvolle Zeit zu nennen, wann er wieder kommen kann.
Eine kleine Unanehmlichkeit ergibt sich in folgendem Fall:
User 1 holt sich einen LOCK, User 2 "klaut" diesen LOCK nach [Zeitstempel LOCK User 1 + x], schließt aber einfach seinen Browser, trödelt selbst oder geht von der Bearbeiten-Seite ohne Abbrechen weg. User 1 ist Beamter und klickt erst nach [Zeitstempel LOCK User 2 + x] auf Speichern. Er könnte nun eigentlich gefahrlos Speichern, wird jedoch, da der LOCK von User 2 noch aktiv (aber obwohl dieser LOCK abgelaufen) ist, auf die Bearbeiten-Start-Seite weitergeleitet ohne zu speichern (Kommt zu Schritt 1). Hier wird dann ein neuer LOCK auf User 1 gesetzt und der LOCK von User 2 inaktiv gesetzt.
Wer so langsam ist, hat es dann aber auch nicht anders verdient und muss die Eingaben wiederholen.
Ich hoffe ich habe jetzt nichts vergessen.
Wenn Du zuviel Zeit hast, kannst Du das natürlich auch um LOCK-Reservierungen erweitern
Gruß hpvw