Announcement

Collapse
No announcement yet.

ado-aktualisierungs-problem, wer weiss rat?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • ado-aktualisierungs-problem, wer weiss rat?

    hallo,<br>
    <br>
    wenn die datenbank im multiuserbetrieb läuft, kommt es manchmal zu folgender meldung:<br>
    "die zum aktualisieren angegebene zeile wurde nicht gefunden. einige werte wurden seit dem letzten lesen ggf geändert."<br>
    dieser dialog verhindert quasi das korrekte beenden der anwendung.<br>
    benutzt man den taskmanager zum beenden und startet erneut, sind aber immer alle daten vollständig vorhanden.<br>
    wie kann ich diesen dialog umgehen?<br>
    oder verhindern das überhaupt so etwas auftritt?<br>
    mfg<br>
    andik

  • #2
    Hallo,

    ich gehe einmal davon aus, dass eine SQL-Datenbank genutzt wird und der Client den Modus <b>clUseClient</b> für die Eigenschaft <b>CursorLocation</b> verwendet. In diesem Fall arbeitet das lokale RecordSet-Objekt von ADO mit einer lokalen Kopie der Daten. Wenn nun eine Änderung gespeichert werden soll, macht ADO intern folgendes:
    <pre>
    UPDATE Tabelle
    SET Spalte1 = NeuerSpaltenWert
    WHERE Spalte2 = AlterSpalte2Wert
    AND Spalte3 = AlterSpalte3Wert
    ...
    </pre>
    Der Update-Vorgang ist immer dann erfolgreich, wenn genau <b>ein</b> Datensatz geändert wurde. <br>
    Wenn allerdings in der Zwischenzeit ein anderer Benutzer den gleichen Datensatz geändert hat, oder ein Trigger vorher einen Wert austauscht, kann es passieren, dass die WHERE-Bedingung <b>keinen</b> Treffer findet. Und hier meldet ADO nur "<i>Die zum aktualisieren angegebene zeile wurde nicht gefunden. einige werte wurden seit dem letzten lesen ggf geändert</i>", da der zu aktualisierende Datensatz nicht mehr über die alten Werte gefunden werden kann.

    Wenn man diese Fehlermeldung umgehen will, so dass <b>jeder</b> Update-Vorgang erfolgreich ist, auch wenn der Datensatz in der Zwischenzeit von einem Dritten geändert wurde, muss folgendes gemacht werden:
    <pre>
    uses ADOInt;

    procedure TForm1.CheckBox1Click(Sender: TObject);
    begin
    with ADODataSet1.Recordset do
    begin
    Properties['Update Criteria'].Value := adCriteriaKey;
    end;
    end;
    </pre>
    Die RecordSet-Eigenschaft <b>Update Criteria</b> wird so gesetzt, dass nur der Primärschlüssel als WHERE-Kriterium verwendet wird. Kommt dann immer noch eine Fehlermeldung, so wurde dieser Datensatz in der Zwischenzeit gelöscht, so dass die lokale Kopie im RecordSet ein "Waisenkind" ist

    Comment


    • #3
      hallo andreas,
      <br><br>
      vielen dank für diese informationen.<br>
      wieviele jahre vergehen, um soviel wissen und information<br>
      anzusammeln?<br>
      oder kommt es mehr auf die richtigen informationsquellen an?<br>
      finde es auf jeden fall klasse, dass man hier nie allein gelassen<br>
      wird.
      mfg
      andi

      Comment


      • #4
        Hallo,

        die Zeitdauer hängt davon ab, wieviel Stunden am Tag man in den MSDN-Unterlagen lesen kann ;-

        Comment


        • #5
          Funktioniert diese Methode

          >> with ADODataSet1.Recordset do
          >> Properties['Update Criteria'].Value := adCriteriaKey;

          auch, wenn man ohne ADO-Komponenten, sondern direkt mit ADO-Objekten von Delphi aus zugreift

          Comment


          • #6
            Selbstverständlich, denn die TADODataSet-Eigenschaft <i>Recordset</i> ist nur das direkte Verbindungsglied (Interface-Zeiger) zum nativen Recordset-Objekt von ADO

            Comment


            • #7
              OK, das habe ich nun also in meine Delphi 6/ADO-Anwendung eingebaut. Nun passiert folgendes Phänomen: Ich starte im Netzwerk das Programm (Multiuser-Zugriff auf Access 2000-Datenbank), das Programm lädt beim Start eine Reihe von Daten aus der Datenbank und zeigt sie im Programmfenster an. In der Zwischenzeit arbeiten andere Leute ebenfalls mit der Datenbank - ich weiss natürlich nicht, ob sie irgendwelche Daten ändern, wenn ich an meinem Rechner sitze. Und dann plötzlich, ohne dass ich am Programm auf meinem Rechner irgendetwas gemacht habe, erscheint die Fehlermeldung

              > die zum aktualisieren angegebene zeile wurde nicht gefunden ...

              warum, um alles in der welt - und wie kann ich das abschalten? - Denn wenn ich die Fehlermeldung wegklicke, lässt sich das Programm nicht mehr bedienen, weil danach weitere Fehlermeldungen kommen.

              Ich muss noch einmal ausdrücklich dazu schreiben, dass mein Programm während der gesamten Zeit absolut passiv ist - also keinerlei Daten aus dem Netz zieht, noch irgendwelche ADO-Funktionen aufruft. Da ist nur diese Fehlermeldung, die aus heiterem Himmel am Schirm erscheint.

              Für sachdienliche Hinweise schon jetzt herzlichen Dank

              Comment


              • #8
                Noch eine Zusatzinformation. Nach der ersten Fehlermeldung

                > die zum aktualisieren angegebene zeile wurde nicht gefunden ...

                lässt sich das Programm nicht mehr bedienen, weil dann die Fehlermeldung erscheint

                > die von der anwendung angeforderte operation ist in diesem zusammenhang nicht erlaubt

                Wer weiss Rat

                Comment


                • #9
                  Hallo,

                  &gt;..Multiuser-Zugriff auf Access 2000-Datenbank...

                  in welcher Konfiguration wird ADO betrieben: clUseClient oder clUseServer? Wird cmdTableDirect für die Eigenschaft <i>CommandType</i> genutzt?

                  Da sich hinter einer ACCESS-Datenbank (*.MDB) kein SQL-Server verbirgt, sondern die Operation vollständig von der lokal installierten <i>Microsoft JET Engine</i> abgearbeitet wird, "muss" die Einstellung <b>clUseServer</b> in Verbindung mit <b>cmdTableDirect</b> verwendet werden. Nur bei einer richtigen SQL-Datenbank ist <b>clUseClient</b> die richtige Wahl

                  Comment


                  • #10
                    Houston, wir haben ein Problem!

                    > in welcher Konfiguration wird ADO betrieben: clUseClient oder clUseServer? Wird cmdTableDirect für die Eigenschaft CommandType genutzt?

                    Ich benutze ja nicht die ADO-Komponenten, sondern greife über native ADO-Objekte - also ich benutze für die RecordSet-Objekte adUseClient (so heisst das glaube ich), und zwar aus dem einfachen Grund, weil adUseServer nicht funktioniert hat und abgestürzt ist, es lag, wenn ich mich recht erinnere, daran, dass in meiner Datenbankanwendung über UPDATE mehrere Datensätze verändert werden, das hat mit adUseServer nicht geklappt.

                    Ansonsten öffne ich die Recordsets mit Open und SQL-Anweisungen - funktioniert eigentlich alles recht problemlos - und (im Vergleich mit den ADO-Komponenten von Delphi) sehr, sehr flüssig und schnell.

                    Aber, da gibt's eben dieses Aktualisierungsproblem, das ich mir einfach nicht erklären kann - ich habe es jetzt schon mit adOpenDynamic und adOpenKeyset probiert, aber es funktioniert einfach nicht - und in Ihrem ADO-Buch, lieber Herr Kosch, finde ich leider dazu auch nichts. Irgendeine Idee

                    Comment


                    • #11
                      Hallo,

                      &gt;Ich benutze ja nicht die ADO-Komponenten, sondern greife über native ADO-Objekte ...

                      es gibt da <b>keinen</b> Unterschied - die Borland-Komponenten sind nur eine zusätzliche "sichtbare" Umverpackung für die nativen ADO-Objekte, damit die Anbindung via TDataSource zur Verfügung steht.

                      &gt;..für die RecordSet-Objekte adUseClient ...

                      Damit muss man aber auch die Einschränkungen akzeptieren, die sich im speziellen Fall einer MDB aus dem doppelt gepufferten Cursor ergeben. Bei dieser Einstellung "simuliert" ADO die Datenbank in einem eigenen Speicherbereich, so dass nicht alle die Funktionen zur Verfügung stehen, die von einer ACCESS-Datenbank unterstützt werden. Mit clUseClient steht kein echter Datensatzzeiger in die MDB zur Verfügung, so dass die JET Engine über eine Simulation genauso mengenorientiert arbeiten muss, wie das im Fall einer "richtigen" SQL-Datenbank der Fall ist. Erst mit clUseServer + cmdTableDirect steht ein echter Datensatzzeiger zur Verfügung, so dass niemals der zu aktualisierende Datensatz über eine logische Abfrage in einer Datenmenge gesucht werden muss. Mit clUseClient gibt es im Gegensatz dazu keine Alternative zur logischen Suche in der Menge. Und wenn diese logische Suche beim UPDATE keinen <b>eindeutigen</b> Datensatz (d.h. nur 1 Treffer in der Datenmenge) findet, so bleibt der JET Engine nichts anderes übrig, als mit der o.g. Fehlermeldung das Handtuch zu werfen.

                      &gt;..eben dieses Aktualisierungsproblem, das ich mir einfach nicht erklären kann ..

                      Dieses Problem kann immer dann auftreten, wenn die Kombination MDB-Datenbank + clUseClient verwendet wird

                      Comment


                      • #12
                        Ja gut, das leuchtet ein - ich werde also versuchen, meine Anwendung so umzubasteln, dass sie mit einer Kombination aus adUseServer und adOpenKeyset läuft (zum Beispiel).

                        Aber: Eins ist mir immer noch nicht ganz klar (ich hoffe, ich frage Ihnen hier keine Löcher in den Bauch, aber mich interessiert's einfach): Mein Programm hat doch mit adUseClient nichts gemacht - und trotzdem kam die Fehlermeldung. Woran liegt das eigentlich? - Kommuniziert Ado von meiner Anwendung aus mit der Datenbank (erkennt dann: Aha, da hat jemand etwas geändert, und spuckt schliesslich die Fehlermeldung aus), ohne dass ich das weiss oder als Programmierer veranlasst habe

                        Comment


                        • #13
                          Hallo,

                          &gt;..Kombination aus adUseServer und adOpenKeyset läuft ..

                          Was soll mit adOpenKeyset erreicht werden? Hinter ACCESS steckt keine SQL-Datenbank, aber ein Key Set macht nur in einer SQL-Datenbank Sinn. Eine SQL-Datenbank arbeitet mengenorientiert, ein Datensatz kann in einer Menge nur dann eindeutig angesprochen werden, wenn der sich in seinen logischen Eigenschaften von den anderen Datensätzen unterscheidet. Aus diesem Grund ist es bei SQL-Datenbanken üblich, für jede Tabellen eine Spalte als Primärschlüssel (Key) vorzusehen, denn in diesem Fall kann ein neuer Datensatz nur dann in dieser Tabelle eingefügt werden, wenn ein eindeutiger Schlüsselwert verwendet wird. Der <i>KeySet Cursor</i> nutzt diesen eindeutigen Identifizierungsweg aus, indem zum Zeitpunkt des Öffnens des Cursors ein Schnappschuss aller Primärschlüsselwerte gemacht wird. Die Ergebnismenge sowie die Datensatz-Sortierung wird somit beim Öffnen des Cursors eingefroren, indem die Liste aller vorgefundenen Primärschlüsselwert in der temp. Tabelle gespeichert wird. Im Gegensatz zum statischen Cursor werden Änderungn am Datensatzinhalt jedoch erkannt, denn nur der Primärschlüsselwert wird in der Cursor-Datenmenge in dieser temp. Tabelle "eingefroren", aber alle anderen Spalten beim Zugriff neu gelesen.

                          &gt;Mein Programm hat doch mit adUseClient nichts gemacht ...

                          Ohne ein Minimal-Beispielprojekt, mit dem sich dieser Effekt jederzeit reproduzieren lässt, kann man an dieser Stelle nichts sagen

                          Comment


                          • #14
                            Und noch einmal adUseServer:

                            Irgendeine Idee, woran es liegen kann, wenn eine Anwendung mit adUseServer und Zugriff auf Access 2000-Datenbank im heimischen Test-Netzwerk einwandfrei läuft, aber auf dem Zielrechner im Netzwerk abstürzt, sobald man irgendeinen Datensatz verändern will? - Mit adUseClient funktioniert's komischerweise. Zielrechner: Windows NT 4.0, Internet Explorer 5.5, Novell-Netzwerk. Testrechner zuhause: Windows 2000, Internet Explorer 5.5.

                            Hilfe!!

                            Comment


                            • #15
                              Hallo,

                              &gt;..Novell-Netzwerk

                              bedeutet dies, dass die ACCESS-Datenbank auf einem Fileserver unter Novell 3.x/4.x läuft? In diesem Fall liegt das Gegenstück zum BDE-Problem vor (die Kombination von BDE + Paradox läuft schlecht auf einem Windows 2000 Server, aber gut auf einem Fileserver mit Novell 3.x/4.x), da Novell als technisch veraltetes Betriebssystem keine der so genannten OpLocks unterstützt. Eine Suche nach der Zeichenkette "OpLocks" liefert hier im FORUM weitere Details.

                              &gt;..Mit adUseClient funktioniert's komischerweise.

                              Weil dann die JET Engine keinen direkten Zugriff über einen Datensatzzeiger auf die MDB-Datei macht, sondern die Ergebnismenge auf den eigenen Rechner kopiert und danach mengenorientiert damit arbeitet. In diesem Fall bleibt der sonst unumgängliche pessimistische Sperrmechanismus außen vor, da das Programm nicht direkt mit dem Datensatz aus der MDB arbeitet, sondern immer nur mit einer Kopie auf dem eigenen Rechner.

                              P.S: Bei der Kombination von einer <b>neuen</b> Datenbank (ACCESS 2000) mit einem von der Technologie her betrachtet biblisch <b>alten</b> Betriebssystem (zumal es nicht von Microsoft stammt) muss man immer mit Problemen rechnen. Im Kleingedruckten findet man nicht ohne Grund oftmals den Hinweis "<i>Änderungen im Interesse des technischen Fortschritts vorbehalten...</i>"

                              Comment

                              Working...
                              X