Neulich bat mich ein Kunde, mir einmal ein Netzwerkproblem bei ihm anzusehen. Aufgrund der Fehlermeldung konnte es keine andere Ursache geben – sie lautete „Aktualisieren nicht möglich, momentane Sperrung durch eine andere Sitzung auf diesem Rechner“. Also haben wir uns diese Sache gemeinsam angesehen und zunächst schien die Meldung plausibel – immerhin arbeitete eine andere Mitarbeiterin gerade mit der Datenbank und es konnte gut sein, dass der Datensatz gesperrt war. Allerdings trat das Problem später immer noch auf, obwohl niemand sonst mehr mit der Datenbank arbeitete. Gemeinsam sind wir dem Problem dann auf die Schliche gekommen. Die Überschrift deutet es bereits an: Ein Memofeld spielte eine große Rolle bei der Lösung des Problems.
Video passend zu diesem Artikel:
Wer mag der Fehlermeldung aus Bild 1 nicht glauben, vor allem, wenn die Daten der betroffenen Tabelle tatsächlich von anderen Nutzern verwendet werden?
Bild 1: Fehlermeldung
Stutzig macht dann bei genauerem Hinsehen der Hinweis, dass es sich um eine andere Sitzung auf dem gleichen Rechner handelt. Und da waren wir uns doch recht sicher, dass aktuell nur eine Instanz der Datenbank geöffnet war.
Was als konnte dieses Problem verursachen? Um es etwas genauer zu beschreiben: Es trat immer auf, wenn wir versucht haben, einen der Datensätze der Tabelle in einem Detailformular zu speichern – also in einem Formular, das von einem Übersichtsformular geöffnet wurde, das wiederum die Daten zur Auswahl in einem Unterformular anzeigt.
Hier konnten wir zumindest erkennen, dass die Daten gleichzeitig in zwei verschiedenen Formularen angezeigt wurden. Aber das ist gang und gäbe – ich selbst habe hunderte Datenbanken programmiert, bei denen ein Übersichtsformular und ein Detailformular den gleichen Datensatz anzeigten und nie gab es Probleme beim Bearbeiten dieser Daten.
Und es wurde immer ominöser: Wir stellten fest, dass das Problem nicht immer auftrat, sondern nur dann, wenn das Memofeld in dem betroffenen Datensatz bereits eine Menge Daten enthielt.
Konstellation des Problems
Schauen wir uns an, wie das Problem genau aussieht. Wir haben dieses in einer minimalen Version nachgebaut, um zu experimentieren und eine Lösung zu finden.
Dazu haben wir zunächst eine Tabelle namens tblMemofelder erstellt, die neben dem Primärschlüsselfeld MemoID und einem Feld mit der Bezeichnung des Datensatzes namens Bezeichnung noch ein Memofeld namens Memofeld enthält. Die Tabelle sieht in der Entwurfsansicht wie in Bild 2 aus.
Bild 2: Tabelle zum Reproduzieren des Problems
Dazu haben wir ein Formular mit einem Unterformular hinzugefügt. Das Hauptformular heißt frmMemofeldUebersicht und enthält neben einer Schaltfläche namens cmdDetails noch ein Unterformular namens sfmMemofeldUebersicht. Dieses Unterformular ist über die Eigenschaft Datensatzquelle an die Tabelle tblMemofelder gebunden und zeigt alle drei Felder dieser Tabelle an (siehe Bild 3).
Bild 3: Formular mit einem Unterformular zur Anzeige aller Datensätze der Tabelle tblMemofelder
Wechseln wir zur Formularansicht, sehen wir hier die Daten der Tabelle tblMemofelder (siehe Bild 4).
Bild 4: Formular mit den Daten der Tabelle tblMemofelder in der Formularansicht
Detailformular für die Tabelle tblMemofelder
Um das Szenario zu vervollständigen, haben wir noch ein Formular erstellt, das direkt an die Tabelle tblMemofelder gebunden ist und alle drei Felder dieser Tabelle anzeigt (siehe Bild 5).
Bild 5: Formular zur Anzeige eines Datensatzes der Tabelle tblMemofelder
Hier haben wir noch ein Textfeld namens txtMenge hinzugefügt, mit dem wir die Menge der Zeichen des im Memofeld enthaltenen Textes ausgeben können.
Diese ermitteln wir zu zwei Gelegenheiten:
- Beim Anzeigen eines neuen Datensatzes, also beim Datensatzwechsel und
- beim Ändern des enthaltenen Textes.
Dazu haben wir die folgenden beiden Prozeduren für die entsprechenden Ereignisse hinterlegt:
Private Sub Form_Current() Me!txtMenge = Len(Me!Memofeld) End Sub Private Sub Memofeld_Change() Me!txtMenge = Len(Me!Memofeld.Text) End Sub
Damit sorgen wir dafür, dass wir nicht nur über das Textfeld den Inhalt des Memofeldes sehen, sondern auch noch die aktuelle Länge (siehe Bild 6). Diese spielt, wie wir gleich sehen werden, eine wichtige Rolle bei unserem Problem.
Bild 6: Anzeige von Memofeldinhalten und ihrer Länge
Maximale Anzahl Zeichen ermitteln
Bevor wir uns um die Probleme kümmern, die durch die oben erwähnte Sperrung ausgelöst werden, schauen wir uns zuerst einmal an, wie viele Zeichen wir einem Memofeld über die Benutzeroberfläche zuweisen können. Dazu fügen wir dem Formular eine Schaltfläche hinzu, die solange den Inhalte des Memofeldes vergrößert und speichert, bis es zu einem Fehler kommt. Die Schaltfläche heißt cmdMemofeldAusreizen und löst die folgende Prozedur aus:
Private Sub cmdMemofeldAusreizen_Click() On Error Resume Next Do While Err.Number = 0 Me!Memofeld = Me.Memofeld _ & " Memofeld mit einem sehr langen Text ..." RunCommand acCmdSaveRecord Me!txtMenge = Len(Me!Memofeld) DoEvents Loop On Error GoTo 0 End Sub
Diese fügt solange die Zeichenfolge Memofeld mit einem sehr langen Text … zum Memofeld hinzu, bis ein Fehler ausgelöst wird. Nach jedem Hinzufügen ruft die Prozedur die Anweisung zum Speichern des aktuell im Formular angezeigten Datensatzes auf. Wird ein Fehler ausgelöst, endet die Do While-Schleife, die solange läuft, bis Err.Number nicht mehr den Wert 0 enthält.
Nach den ersten paar Durchläufen haben wir allerdings gesehen, dass wir bei der Länge der hinzuzufügenden Zeichenkette ewig brauchen werden, um das Memofeld zu füllen und haben die Zeichenkette um ein Vielfaches verlängert. Bei etwas über 7.000.000 Zeichen erschien dann allerdings nicht etwa eine Fehlermeldung, sondern Access konnte die Anforderung nicht mehr verarbeiten und fror ein. Das geschieht allerdings auch, wenn wir in diesem Zustand versuchen, manuell weitere Zeichen einzugeben. Das Schließen der Anwendung gelang anschließend nur über das Beenden des Tasks im Taskmanager.
Diese Menge an Zeichen erreichen wir allerdings längst nicht, wenn wir uns das oben angerissene Problem ansehen.
Memofeld in zwei Formularen gleichzeitig geöffnet
Nun nutzen wir die oben erstellten Formulare zum Reproduzieren unseres Problems. Dabei öffnen wir zuerst das Formular frmMemofeldUebersicht, markieren den zu untersuchenden Eintrag und öffnen dann mit der Schaltfläche Details das Detailformular frmMemofeldDetails (siehe Bild 7). Der zu untersuchende Eintrag enthält aktuell nur wenige Zeichen, in diesem Fall 39.
[
Bild 7: Anzeige des Inhalts eines Memofeldes in zwei verschiedenen Formularen gleichzeitig
Dort fügen wir nun einige weitere Zeichen ein, sodass das Memofeld beispielsweise 3.000 Zeichen anzeigt. Auch das ist kein Problem! Also was führt nun zu dem eingangs erwähnten Fehler?
Schließen wir einfach nochmal das Detailformular und aktualisieren den Inhalt des Übersichtsformulars mit F5. Dann öffnen wir den Detaildatensatz erneut und versuchen diesen zu bearbeiten. Und dann tritt der Fehler auf – siehe Bild 8.
Bild 8: Fehler beim Ändern des Inhalts des Memofeldes
Was hat sich nun geändert? Im Gegensatz zum vorherigen Beispiel versuchen wir nun, einen bereits recht langen Inhalt eines Memofeldes zu ändern. Zuvor war die gespeicherte Version des Memofeldes noch nicht so lang. Der Unterschied ist also, dass beim Auftreten des Fehlers die zu ändernde Version bereits eine gewisse Anzahl Zeichen enthielt.
Um den Bedingungen, unter denen der Fehler auftritt, auf die Schliche zu kommen, experimentieren wir nun ein wenig mit der Anzahl der Zeichen, ab welcher der Fehler ausgelöst wird.
Bearbeitung löst keinen Fehler aus, wenn nur ein Formular auf das Memofeld zugreift
Dazu schließen wir erst einmal das Formular frmMemofeldDetails und leeren das Memofeld im Formular frmMemofeldUebersicht.
Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...
den kompletten Artikel im PDF-Format mit Beispieldatenbank
diesen und alle anderen Artikel mit dem Jahresabo