Announcement

Collapse
No announcement yet.

ADO / Access / ClClient / Multiuser

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

  • ADO / Access / ClClient / Multiuser

    Bei delphi / Ado / Access datenbank
    Ich habe cursorlocation auf clclient ( Geschwidickeit ? SortBy )
    Ist es doch moglich eine Sperre aufbauen, dass die andere benutzer, ein datei nich mehr ander konnen, wenn der erste benutzer die datei schon geander hat.
    Ich kann nich 50% von datei auf der Serveur schiken ( Wegen schon geander von eine andere Kunde )

    Mus ich umbeding mit clserveur arbeiten fur diese lossung oder gieb es andere moglichkeit

    Schuldigung fur die fehller ich bin franszosiche...

  • #2
    Hallo,

    >..cursorlocation auf clclient ..

    in diesem Fall puffert der OLE DB Provider <i>Microsoft JET Engine</i> die Datenmenge in einem eigenen Speicherbereich, so das alle Schreibzugriffe zuerst nur auf die lokale Kopie erfolgen.

    Aber auch dann, wenn bei clUseServer für die TADODataSet-Instanz das pessimistische Sperrverfahren angefordert wird, verhält sich die Anwendung nicht so wie erwartet:
    <pre>
    ADOConnection1.Connected := True;
    ADODataSet1.LockType := ltPessimistic;
    ADODataSet1.CursorType := ctKeyset;
    ADODataSet1.Active := True;
    </pre>
    Wenn zwei Programminstanzen auf den gleichen Datensatz zugreifen, können beide Programminstanzen in den Edit-Modus schalten, die Daten editieren und Posten. Der "Letzte" gewinnt dabei, so dass bei Instanzen nach dem Aktualisieren der Daten immer den Wert des letzten Posts sehen.

    Wird nur mit den nativen ADO-Objekten gearbeitet, tritt dieser Effekt nicht auf. Das Problem liegt also bei ADO Express - genauer gesagt liegt die Ursache im internen VCL-Cache. Denn erst beim Aufruf der Methode <b>Post</b> bekommen die nativen ADO-Objekte mit, dass der Anwender ein Feld des aktuellen Datensatzes geändert hat. Damit sich ADO Express genauso wie die nativen ADO-Objekte verhält, ist ein kleiner "Kunstgriff" notwendig, wie der nächste Versuch zeigt: Immer dann, wenn der Dummy-Edit-Modus aktiviert ist, sorgt das Programm dafür, dass in der Ereignisbehandlungsmethode für das <b>BeforeEdit</b>-Ereignis der TADODataSet-Instanz ein Dummy-Update auf die Hilfsspalte der Tabelle (Beispiel: <i>EditUser</i>) gemacht wird, indem das Programm an TADODataSet vorbei direkt auf die darunterliegende Recordset-Objektinstanz zurückgreift:
    <pre>
    Recordset.Fields.Item['EditUser'].Value := sUserName;
    </pre>
    Damit keine wichtige Information überschrieben wird, verwendet die Tabelle die zusätzliche Spalte <i>EditUser</i>, die ständig mit dem jeweiligen Benutzernamen überschrieben wird.
    <pre>
    {
    Hilfsfunktion stempelt unmittelbar vor jedem Editiervorgang (am besten
    aus der Ereignisbehandlungsmethode BeforEdit heraus) den aktuellen
    Benutzernamen auf ein Hilfsfeld der Tabelle. War das erfolgreich,
    liefert die Funktion TRUE zurück.
    }

    function LockEditUser(DataSet: TDataSet): Boolean;
    begin
    Result := False;
    with DataSet as TCustomADODataSet do
    if CanModify and
    (CursorLocation = clUseServer) and
    (LockType = ltPessimistic) then
    begin
    UpdateCursorPos;
    Recordset.Fields.Item['EditUser'].Value := sUserName;
    Result := True;
    end;
    end;

    procedure TForm1.ADODataSet1BeforeEdit(DataSet: TDataSet);
    begin
    if RadioGroupMode.ItemIndex = 2 then
    if not LockEditUser(ADODataSet1) then
    begin
    MessageBeep(0);
    Abort;
    end
    end;

    procedure TForm1.ADODataSet1BeforePost(DataSet: TDataSet);
    begin
    ADODataSet1EditUser.Clear;
    end;
    </pre>
    Wird anstelle von TADODataSet die FreeWare-Komponente <b>TBetterADODataSet</b> (siehe <i>http://web.orbitel.bg/vassil/</i>) eingesetzt, so vereinfacht sich die Implementierung. TBetterADODataSet macht die notwendigen Schritte immer dann automatisch, wenn die folgenden Kriterien eingehalten werden:<br>
    1. CursorLocation ist <b>clUseServer</b> <br>
    2. LockType ist <b>ltPessimistic</b> <br>
    3. OLE DB-Provider ist die Jet-Engine (ACCESS-Datenbank

    Comment


    • #3
      @Hr. Kosch<br>
      treffen o.g. Aussagen auch für SQL-Server zu?<br>
      Ich verwende TBetterADODataSet und SQL-Server 2000 sowie D5E.<br>
      Hendri

      Comment


      • #4
        Hallo,

        ein SQL-Server wird normalerweise generell über eine optimistische Sperre angesprochen, da dort nur der Prozess des SQL Servers selbst Zugriff auf die Datenbankdatei hat. Im Fall von ACCESS (datensatzorientierte Desktop-Datenbank) greift jeder Client direkt auf die physische Datenbankdatei zu, so dass dort im Mehrbenutzerbetrieb pessimistische Sperren notwendig sind, um die Datenintegrität zu schützen.

        Im Fall des SQL Server ist die CursorLocation <b>clUseClient</b> die bessere Wahl, so dass pessimistische Sperren (über die Transaktion) erst gar nicht verfügbar sind. Da TBetterADODataSet sowohl den Provider (JET Engine) als auch die CursorLocation (clUseServer) prüft, ist der TBetterADODataSet-Mechanismus beim Microsoft SQL Server immer deaktiviert. Ein Mehrbenutzerkonflikt macht sich daher erst beim Post der Änderung bemerkbar.
        &#10

        Comment


        • #5
          Hallo,<p>
          genau hier haben wir ein Problem mit einer Accesstabelle wenn ein <b>AutoInc</b>-Feld drin ist. Sobald die Datenbank in den Edit-Modus gehen soll, kommt die Meldung, "Feld kann nicht akutalisiert werden". Bei Insert klappt alles... (AdoDataset / BetterAdoDataSet402)...<p>
          Hat jemand noch eine Idee?<p>
          Schöne Grüße, Mario Noac
          Schöne Grüße, Mario

          Comment


          • #6
            Hallo,

            &gt;..mit einer Accesstabelle wenn ein AutoInc-Feld drin ist..

            dieser Sonderfall wird von TBetterADODataSet extra geprüft.
            Wenn die erste Spalte der Tabelle kein AUTOINCREMENT-Feld ist, das von der Jet Engine automatisch hochgezählt wird, schreibt TBetterADODataSet den alten Wert neu in diese 1. Spalte. Wird allerdings ein AUTOINCREMENT-Feld vorgefunden, passiert dies mit der <b>2. Spalte</b> der Tabelle.
            <pre>
            Procedure TBetterADODataSet.InternalEdit;
            Begin
            Inherited;
            //This code was provided by Harry Van Tassel.
            If (CursorLocation=clUseServer) And
            (LockType=ltPessimistic) And
            CanModify And
            Not(BOF And EOF) And
            (Pos('JET.OLEDB', UpperCase(Connection.Provider))>1) Then
            Begin
            UpdateCursorPos;
            FLockCursor:=Nil;
            FLockCursor:=Recordset.Clone(ADOInt.adLockUnspecif ied);
            With FLockCursor Do Begin
            BookMark:=RecordSet.BookMark; {sync the cloned cursor}
            If (Fields[0].Properties['ISAUTOINCREMENT'].Value=False) Then
            Fields[0].Value:=Fields[0].Value
            Else If (Fields.Count>0) Then
            Fields[1].Value := Fields[1].Value;
            End; //With
            End;
            End;
            </pre>
            Wenn die eigene Tabelle auch in der 2. Spalte keinen geeigneten Datentyp nutzt, muss man <br>
            a) entweder den Sourcecode von TBetterADODataSet ändern, oder <br>
            b) zu meinem manuellen Weg wechseln

            Comment

            Working...
            X