![]() |
Datenbank: Access • Version: 2003 • Zugriff über: ADO
Datensatzsperre mit Access
Hi, ich habe ein mittelschweres Problem und komme nicht dahinter. Ich muss an einer bestehenden Anwendung eine Änderung vornehmen. Die Anwendung benutzt eine Access-Datenbank, die im Netzwerk abgelegt ist. Für eine spezielle Funktion muss ich in einer Tabelle einen Datensatz sperren, bzw. muss prüfen können, ob der Datensatz schon von einem anderen Client gesperrt ist. Ich bekomme es einfach nicht hin.
Ich habe mit allen möglich Einstellungen der ADO Komponente gespielt, allerdings ohne ein Ergebnis.
Delphi-Quellcode:
Also, der Client 1 soll diesen bestimmten Datensatz sperren, diesen Datensatz aktualisieren und dann die Sperre wieder aufheben. Das dauert vielleicht 50ms, also ganz kurz.
.CursorLocation := clServer
.Cursortype := ctStatic .CommandType := ctTableDirect .LockType := ltPessimistic Wenn der Client 2 das selbe macht, dann muss ich irgendwie feststellen können, ob der Datensatz gesperrt ist oder nicht. Falls er gesperrt ist, dann muss das Programm einen kurzen Moment warten und dann noch mal probieren, damit ich den aktuellen Wert auslesen kann. Kann mir jemand helfen, wie ich das anstellen kann? Edit: Ich habe schon hier im Forum gesucht und alles was ich gefunden habe, hat mir nicht geholfen. Im Web steht dann auch nur mit TableDirect und Pessimistic locking, aber anscheinend bin ich zu doof. |
AW: Datensatzsperre mit Access
Imho ist Access absolut nicht für multiuser-Zugriff geeignet.
|
AW: Datensatzsperre mit Access
Ja, das ist mir auch klar, aber ich kann da im Moment leider nichts dran ändern, da mir das vorgegeben wurde. Zu 98% wird das Programm ja auch als Einzelplatz-Version benutzt und da gibt es ja auch keine Probleme. Nur für diese 2% bei dem mal zwei Benutzer gleichzeitig auf die Datenbank zugreifen, bzw. den einen Datensatz aktualisieren müssen, muss ich eine Lösung finden. Über die ganzen Infos, die ich im Web gefunden habe, muss es auch irgendwie möglich sein, nur bekomme ich es einfach nicht hin.
Über das grundsätzliche Access Problem brauchen wir hier nicht zu diskutieren, das ist mir bekannt und wenn es nach mit ginge, würde ich das auch ändern, aber wie das immer so geht, nach mir geht es halt nicht. |
AW: Datensatzsperre mit Access
Hallo,
bekommst Du die Sperrung hin, wenn Du mit BeginTransaction anfängst, dann die Änderungen machst und dann ein Commit und EndTransaction? |
AW: Datensatzsperre mit Access
Vielleicht hilft es wenn du vor der Tabelle eine Protokoll-Tabelle vorschaltest. Zwar ist das nicht die optimale Lösung, aber vielleicht hilft es um die 2% Fälle abzudecken.
|
AW: Datensatzsperre mit Access
Quick and Dirty:
Ein zusätzliches Feld in der Tabelle anlegen, das gesetzt wird, sobald der Datensatz bearbeitet wird und das vor jedem Bearbeiten geprüft wird. Alternativ in einer separaten Tabelle beim Bearbeiten eines Datensatzes den Namen der Tabelle und die ID des gerade Datensatzes speichern und die Tabelle vor jedem Bearbeiten abfragen, ob der aktuelle Datensatz dort aufgeführt ist. Und für die Zukunft folgende Aussage: Zitat:
|
AW: Datensatzsperre mit Access
Mit Transaktionen habe ich auch schon probiert, da komme ich aber auch zu keinem Ergebnis. Wenn ich testweise mit zwei Arbeitsstationen für den besagten Fall zur gleichen Zeit auf "Speichern" klicke, bekomme ich jedesmal die selbe (fotlaufende) Nummer vergeben. Ich bekomme keine Fehlermeldung, dass da jetzt was gesperrt ist oder so.
Mit einer "Protokoll-Tabelle" habe ich es auch schon probiert. Ich schreibe da einen Datensatz mit dem Computernamen beim Speichern, dann suche ich mir die nächste Nummer raus, dann prüfe ich noch mal den Computernamen in der "Protokoll-Tabelle" und wenn das der gleiche ist, dann nehme ich die Nummer, ansonsten hole ich noch mal die "Neue". Funktioniert aber auch nicht. Ich bin der Meinung, dass es nicht viel sein kann, dass ich einfach in den entsprechenden Eigenschaften falsche Werte drin habe. Oder es ist ein grundsätzlicher Bug in den ADO-Komponenten und da wird es schwer etwas zu finden. Als Dirty-Version habe ich mir schon überlegt, dass ich eine Datei Exclusiv in dem Ordner erstelle, in dem die Access-Datenbank liegt und und diese wieder lösche, wenn der Vorgang beendet ist. Wenn der zweite Client das selbe versuchen will, gibt es da halt eine Fehlermeldung, da er die Datei ja nicht auch noch anlegen kann. Die Fehlermeldung fange ich dann natürlich ab und probiere es dann z.B. nach 50ms noch mal, solange bis es klappt. Wie gesagt, dirty und es könnten mir eventuell dadurch noch andere Probleme entstehen, wie z.B. die Datei kann nicht gelöscht werden usw. Laut meinen Informationen müsste es aber auch direkt in Access gehen. Ich hoffe, ich bekomme das noch raus oder es hat schon mal jemand mit dem selben Problem zu tun gehabt. |
AW: Datensatzsperre mit Access
@HeikoAdams: Wo ist denn das Zitat her?
|
AW: Datensatzsperre mit Access
Vielleicht ist
![]() |
AW: Datensatzsperre mit Access
Zitat:
Wenn bei meinen Programmen irgendein Szenario Probleme macht, wird es solange nicht offiziell unterstützt, bis es eine praktikable und sichere Lösung für die Probleme gibt :wink: |
AW: Datensatzsperre mit Access
@HeikoAdams: Das muss ich mir mal merken, das ist gut.
Ich habe das Problem jetzt gelöst, bzw. weiß jetzt wie es funktioniert und auf was man achten muss. Mein Problem war, das ich als "Protokoll-Tabelle" eine vorhandene Tabelle benutzt habe. Die Tabelle hat nur zwei Felder, ein Beschreibungsfeld und ein Memofeld. Meinen Code habe ich wie folgt aufgebaut:
Delphi-Quellcode:
Das Problem war, das mein Feld "Info" ein Memofeld ist. Mit Änderungen in Memofeldern funktioniert es nicht.
ADODataSet.SQL.Text := 'SELECT * FROM PROTOKOLL WHERE DESC="BelegNumLocked"';
ADODataSet.Open; ADODataSet.FieldByName('Info').AsString := '<lokaler Computername + Zeitstempel>'; xxx.. ---> mach irgendwas try ADODataSet.Post; except on E: Exception do begin // Fehler beim Post isError := True; end; end; Ich habe mir dann eine zusätzliche Tabelle angelegt, in der kein Memofeld ist und dann funktioniert es mit obigem Code. (Tabellenname natürlich anders) Wenn zwei Clients dann zur selben Zeit die Funktion ausführen, dann bekommt der letztere beim Post folgende Exception
Code:
Diese Exception fange ich ja wie angegeben ab und reagiere entsprechend drauf.
Die zum Aktualisieren angegebene Zeile wurde nicht gefunden. Einige Werte wurden seit dem letzten Lesen ggf. geändert.
Folgendes noch zur Info: Es ist egal, ob ich in der Ado-Komponente bei LockType Optimistic oder Pessimistic locking eingestellt habe, es funktioniert mit beiden Einstellungen. Bei Cursortype und CommandType ist es auch egal, was eingestellt ist. Bei CursorLocation muss zwingend clClient eingestellt sein, mit clServer funktioniert es nicht, da wird immer das Post ohne Fehler ausgeführt. Es ist egal, ob in der Tabelle ein ID-Feld als Primary Key enthalten ist oder nicht. Ich hoffe, das andere mit diesen Informationen auch einen Nutzen von haben. Hiermit ist auch bewisen, dass ich auch Access in einem Netzwerk einsetzen kann (mal davon abgesehen, ob das Sinn macht oder nicht). Wenn man z.B. in einer kleinen Firma nur zwei PC's hat und alle Daten auf einer Netzwerkfestplatte abgelegt sind (kein Server vorhanden) und die Datenmenge überschaubar ist, dann kann man damit schon gut arbeiten, denke ich. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:23 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz