Announcement

Collapse
No announcement yet.

Recordlocking mit native ADO

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

  • Recordlocking mit native ADO

    Ist es möglich, mit nativen ADO-Objekten Datensätze zu sperren - normalerweise müsste das ja gehen, wenn man adLockPessimistic beim Recordset einstellt - allerdings finde ich nirgendwo eine Möglichkeit, ein Recordset in den Edit-Modus zu versetzen.

    Danke für alle sachdienlichen Hinweise.

  • #2
    Hallo,

    welche Datenbanken (genauer gesagt, welcher <i>OLE DB Provider</i>) wird verwendet? Im Fall von einer ACCESS-Datenbank (MS JET Engine ist der Provider) reicht das Recordset-Objekt bei geeigneter Konfiguration den neu zugewiesenen Wert <b>sofort</b> an die Datenbank weiter. Ein spezieller Edit-Modus ist nicht notwendig.

    Siehe auch <a href="/webx?50@@.ee8d7c4/11">Mario.Noack "Pessimistische Sperre mit TADODataset" 03.12.2002 09:36</a>
    &#10

    Comment


    • #3
      Hallo Herr Kosch,

      Access wird verwendet - und wenn's da keinen Edit-Modus gibt, sehe ich darin ein echtes Problem, denn dann lässt sich ja wohl auch keine vernünftige pessimistische Datensatzsperre verwirklichen, weil jeder bei einem Multiuser-Zugriff in der Datenbank herumfuhrwerken und Änderungen anderer Benutzer überschreiben kann, oder?

      Ich tüftele schon seit Wochen an einem Delphi-Frontend für eine (Kundenwunsch!) Access-Datenbank herum, die im Netzwerk zum Einsatz kommen soll. Ganz ehrlich: Ich kann Ihre Euphorie für ADO nicht so ganz nachvollziehen. Unter BDE ist der Netzwerkzugriff auf dBase-Datenbanken wirklich plausibel geregelt. Nachdem ich tagelang die Ado-Komponenten von Delphi 6 Enterprise getestet hatte, fielen mir verschiedene Merkwürdigkeiten auf (u.a. auch die pessimstische Datensatzsperre). Ich habe dann einmal Tests mit native ADO gemacht (ADODB_TLB eingebunden und dann alles von Hand). Ergebnis: Das ganze funktioniert wirklich rasend schnell im Vergleich etwa zu TADOConnection + TADODataset. Aber wenn ich keine Datensätze sperren kann, ist das auch alles für die Katz'

      Comment


      • #4
        Hallo,

        &gt;..denn dann lässt sich ja wohl auch keine vernünftige pessimistische Datensatzsperre verwirklichen..

        doch - die pessimistische Sperre ist wirksam. Wie die Abbildung 6.58 auf der Seite 315 in meinem Buch <i>ADO und Delphi</i> zeigt, erhält der 2. Benutzer sofort das Veto, wenn er den Edit-Button im TDBNavigator anklickt, obwohl zur Zeit ein anderer Benutzer bereits an diesem Datensatz schafft.

        &gt;..Nachdem ich tagelang die Ado-Komponenten von Delphi 6 Enterprise ..

        Das Problem liegt nur darin, dass die ADO Express/dbGo-Komponenten der VCL nur "anders ticken" als die nativen ADO-Objekte. Man hat daher die Wahl zwischen 2 Wegen: <br>
        1. <b>TBetterADODataSet</b> einsetzen, da diese FreeWare-Komponente speziell die Besonderheiten von ACCESS-Datenbanken berücksicht <br>
        2. TADODataSet-Ereignis <b>BeforeEdit</b> auswerten und dort durch den direkten Zugriff auf die Fields-Kollektion des nativen Recordsets den Datensatz als "schmutzig" abstempeln, so dass die pessimistische Sperre greift.
        <pre>
        DataSet1.Recordset.Fields.Item['SperrSpalte'].Value := 'DummyWert';
        </pre>
        Die VCL-Komponenten reichen den Schreibzugriff erst beim Post an das native Objekt weiter, daher greift die pessimistische Sperre so spät, dass sie wirkungslos wird. Nur durch den direkten Zugriff auf das darunterliegende Recordset-Objekt erzielt man das gewünschte Ergebnis.

        &gt;Ganz ehrlich: Ich kann Ihre Euphorie für ADO nicht so ganz nachvollziehen.

        ADO ist als eierlegende Wollmilchsau in Form einer universellen Datenbankzugriffsschicht konzipiert, wobei die SQL-Server bevorzugt werden (nur der Vorläufer DAO war speziell für ACCESS-Datenbanken geeignet). Somit darf man die Beschränkungen des ACCESS-Datenbankformats (genauer gesagt das Verhalten des OLE DB-Providers <i>Microsoft JET Engine</i>) nicht ADO anlasten

        Comment


        • #5
          Lieber Herr Kosch,

          das mit der "eierlegenden Wollmilchsau" kann ich durchaus nachvollziehen - aber die Geschichte mit dem Stempel nicht. Ein Stempel ist doch etwas, was man sehen können muss - ich hab' Ihnen das ja schon mal geschrieben, aber darauf keine plausible Antwort bekommen. Also, Sie schreiben hier (und auch in Ihrem ADO-Buch):

          >> TADODataSet-Ereignis BeforeEdit auswerten und dort durch den direkten Zugriff auf die Fields-Kollektion des nativen Recordsets den Datensatz als "schmutzig" abstempeln.

          Soweit sogut: Nun baue ich in mein Programm eine Routine in "BeforeEDit" ein, die dem Datensatz auf einem Hilfsfeld einen Stempel verpassen soll. Wenn zur gleichen Zeit ein anderer den Datensatz editiert, dann meldet sich ADO nach etwa ein, zwei Sekunden mit der Meldung "aktualisierung nicht möglich, datensatz gesperrt". Alles bestens - die pessimistische Sperre funktioniert also, ABER der Stempel funktioniert nicht, wenn kein anderer den Datensatz editiert.

          Ich sag Ihnen mal, wie ich das mit native ADO bewerkstellige: Vor dem Editieren frage ich ein Hilfsfeld auf einen Inhalt ab - ist das Feld gefüllt (zum Beispiel mit dem UserNamen eines anderen Benutzers), dann meldet sich das Programm ruckzuck mit: "Datensatz gesperrt von Benutzer XY". Ist das Feld leer, kann ich über recordset.Update (Hilfsfeld, Username) einen Benutzer eintragen - und dann mit dem Editieren beginnen. Nun bekommen alle anderen eine Fehlermeldung im Stil "Datenstz gesperrt von Benutzer XY". Am Ende des Editierens wird der Eintrag im Hilfsfeld gelöscht - fertig. Es funktioniert.

          Glaubt man Ihrer Theorie mit dem direkten Zugriff auf das darunterliegende Recordset-Objekt, dann müsste es möglich sein, bei ADO-Zugriff über VCL-Komponenten ebenfalls das Hilfsfeld "abzustempeln". Ich trage also ins BeforeEdit-Ereignis den Stempel-Code ein (AdoDataset.Recordset.Update (Hilfsfeld, Username)), und der Code wird vom Programm klaglos abgearbeitet - ABER: gestempelt wird erst, wenn über VCL gepostet wird - sprich: Der UserName bleibt für sämtliche anderen Benutzer im Netzwerk unsichtbar, solange ich den Datensatz bearbeite, erst beim Posten wird er eingetragen (trotz des direkten Zugriffs auf das darunterliegende Recordset-Objekt), und nach dem Posten gibt das natürlich keinen Sinn mehr. Sprich: Es funktioniert nicht

          Comment


          • #6
            Hallo Wolfgang,<p>
            Dir ist ein Fehler unterlaufen: Andreas schrieb<br>
            <i>2. TADODataSet-Ereignis BeforeEdit auswerten und dort durch den direkten Zugriff auf die Fields-Kollektion des nativen Recordsets den Datensatz als "schmutzig" abstempeln, so dass die pessimistische Sperre greift.</i><br>
            Heißt, im OnBevorEdit bist Du schon richtig, aber der Zugriff zum Feld ändern muss über das Recordset, des Datasets erfolgen, auf keinen Fall über das Dataset selbst. Der Clou müsste da sein, dass die direkten Änderungen am Recordset dem Dataset nicht mitgeteilt werden.... und es sollte somit wieder funktionieren. Die Felder, die über das Dataset bearbeitet werden können, haben mit den Feldern des RS nichts zu tun.<br>
            <pre> ADODataSet.Recordset.Fields['??'].Value := ??
            </pre><p>
            Noch was: Ich finde die Methode nicht schlecht, aber wie will man so sicherstellen, dass nicht zwei Leute gleichzeitig lesen, feststellen, alles OK und locken? Das mögliche Zeitfenster dafür ist nicht groß, aber es ist da und nicht weg zu diskutieren, oder etwa doch?<p>
            Schöne Grüße, Mario Noac
            Schöne Grüße, Mario

            Comment


            • #7
              Hallo,

              es ist die Aufgabe des OLE DB-Providers (also der MS JET Engine), die pessimistische Sperre umzusetzen. Auch wenn der "Stempel" mit einer zeitlichen Verzögerung in die MDB-Datei geschrieben wird, kann nur ein Benutzer einen Datensatz abspempeln. Die beteiligten Recordset-Objektinstanzen von verschiedenen Anwender sind nur der Überbringer des "Stempels", aber sie steuern das Ganze nicht selbst

              Comment


              • #8
                Hallo Andreas,<p>
                aber wenn beide Parteien mit nur einem sehr kleinen Zeitversatz lesen und und dann entsprechend den Wert schreiben, wer verhindert, das letzterer den Wert des ersten in der Lock-Spalte überschreibt? Um das zu verhindern, bräuchte ich doch genau die SPerre, die ich zu simulieren versuche?!<p>
                Schöne Grüße, Mario Noac
                Schöne Grüße, Mario

                Comment


                • #9
                  Hallo,

                  &gt;..wer verhindert, das letzterer den Wert des ersten in der Lock-Spalte überschreibt?

                  die MS JET Engine, denn der aktuelle Datensatz bleibt in der Datenbank bei der pessimistischen Sperre nach dem "Abstempeln" solange als gesperrt markiert, bis der Vorgang abgeschlossen bzw. zum nächsten Datensatz gewechselt wird. ACCESS arbeitet als Desktop-Datenbank mit Datensatzzeigern, so dass ein 2. Benutzer nur dann einen Wert eines Datensatzes ändern kann, wenn kein anderer Benutzer im pessimistischen Sperrverfahren zuvor einen Spaltenwert dieses Datensatzes geändert hat. Die MS JET Engine simuliert für ACCESS-Datenbanken nur das, was bei den SQL-Servers über eine laufende Transaktion automatisch passiert. Solange der Anwender A seine "Transaktion" nicht beendet (Post/Datensatzwechseln), bekommt ein Anwender B beim Versuch des "Drüberstempelns" sofort das Veto, da die "schmutzige Transaktion" des Anwenders A noch offen ist

                  Comment


                  • #10
                    ... das heißt, es ist eigentlich ausreichend, zu versuchen, den Datensatz zu stempeln?<p>
                    <pre>try
                    Dataset.recordset.field[??].Value := irgendwas;
                    except
                    ShowMessage('Bereits gesperrt');
                    end;</pre>
                    <p>
                    Naja, ich glaube mal, ich werde das für mich mal in aller Ruhe über Weihnachten testen oder hast Du vielleicht in Deinem Ado-Buch ein fertiges Beispiel?<p>
                    Schöne Grüße, Mario Noac
                    Schöne Grüße, Mario

                    Comment


                    • #11
                      Hallo Herr Kosch,

                      > Solange der Anwender A seine "Transaktion" nicht beendet (Post/ Datensatzwechseln), bekommt ein Anwender B beim Versuch des "Drüberstempelns" sofort das Veto, da die "schmutzige Transaktion" des Anwenders A noch offen ist.

                      das klingt für mich irgendwie plausibel - werde ich mal versuchen, nachzuvollziehen. Obwohl meine Methode anscheinend auch funktioniert (also: ins Hilfsfeld den jeweiligen User eintragen (per Recordset.Update), weil dann in einem Netzwerk alle anderen gleich wissen: Aha, der und der ist gerade mit dem Datensatz beschäftigt.

                      Herzliche Grüsse und vielen Dank

                      Comment

                      Working...
                      X