DacPagedDataStore vs. Array ?

Zugriff, Engines, Konvertierung. Von ADS über DBF bis zu SQL.

Moderator: Moderatoren

Antworten
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

DacPagedDataStore vs. Array ?

Beitrag von AUGE_OHR »

hi,

XbpQuickBrowse() verwendet ja ein DacPagedDataStore() für eine DBF oder Array.
wenn ich aber ein Array habe, wozu brauche ich dann noch DacPagedDataStore() ?

DacPagedDataStore() hat ja einen "seitenorientierten Cache" ... wäre das nicht auch ein Array ?

ok die "Browse" beinhalten auch noch die "Navigation" aber die habe ich doch eh in einem Array System zum "navigieren".

wenn ich nun mit XbpQuickBrowse() eine DBF verwende "lädt" mir DacPagedDataStore() die "Felder" in ein Array um es dann in der betreffenden "Cell" anzuzeigen.

wenn ich mir nun das ansehen

Code: Alles auswählen

nRows := AScan( ::VisibleRecords, DAC_RecId( aData ) )
sieht es mir so aus als wenn er in seinem "Cache" ( Array ) nach Werten sucht und sonst "nach-lädt".

Frage : woher "weiss" der "Cache" ob die "Werte" noch "aktuell" sind ?

wenn ich die "Technik" nun auf DBF übertrage würde es bedeuten das ich jeden Datensatz den ich "lese" auch gleich in ein Array aufnehme ... :-k

Frage : sollte man sich auf DacPagedDataStore() "verlassen" oder ist sein "eigenes" Array System bauen :?:
gruss by OHR
Jimmy
Benutzeravatar
Friedhelm
Cut&Paste-Entwickler
Cut&Paste-Entwickler
Beiträge: 46
Registriert: Sa, 08. Apr 2006 17:20
Wohnort: Leverkusen
Kontaktdaten:

Re: DacPagedDataStore vs. Array ?

Beitrag von Friedhelm »

Hi Jimmy,

Die DacPagedDataStore Klasse erfüllt die Aufgabe ein PreCaching der anzuzeigenden Datenwerte vorzunehmen, um ein schnelleres Browsen zu ermöglichen und stellt standardisierte Navigationsmethoden für den Datenzugriff zur Verfügung. Wenn Du eine DacPagedDataStore Klasse für eine DBF-Datei einrichtest, werden die Daten für den Cache aus der DBF-Datei in die Pages (interne Arrays) übernommen. Dies geschieht bei einem Refresh. Falls Du eine DacPagedDataStore Klasse auf ein Array anwendest, werden die internen Arrays für die Pages als Referenz in Cache übernommen.

Du kannst Dir aber auch eine eigene Klasse schreiben, die diese Funktionen übernehmen und als für den Browser als Datalink übergeben. Du mußt nur sicherstellen, dass alle notwendigen Instanzen vorhanden sind. Ich habe dies bereits durchgeführt um eine Datenzugriff ADS mit Low-Level Funktionen bereitzustellen. Dies funktioniert einwandfrei. Wie du dabei die Refreshingzyklen einbaust, bleibt Dir selbst überlassen.

Leider ist in der Dokumentation die DacPagedDataStore Klasse nur ungenügend beschrieben und es sind nicht alle Instanzen aufgeführt. Wenn Du dir den Sourcecode für den Quickbrowse anschaust, wird einiges deutlicher.
Gruß Friedhelm
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: DacPagedDataStore vs. Array ?

Beitrag von AUGE_OHR »

Friedhelm hat geschrieben:Dies geschieht bei einem Refresh.
aha ...
Friedhelm hat geschrieben:Wenn Du dir den Sourcecode für den Quickbrowse anschaust, wird einiges deutlicher.
genau deshalb meine Frage nach dem "Cache".
mir viel auf das die Daten nicht "aktualisiert" werden solange sie im "Cache" sind.
es wird also nicht, wie beim XbpBrowse(), mittels des "Skipper" in der Daten "Quelle" navigiert sondern in einem "internen" Array.

für die MAPI Schnittstelle im Calender hatte ich die Daten in ein Array geladen. Das habe ich dann erweitert zu einem "Cache".

obwohl die DBF Version deutlich schneller ist hab ich nun das vorhandene "Cache" Verfahren auch darauf angewendet.
im Netzwerk geht nun die "Last" deutlich zurück da nur "neue" Daten gelesen werden müssen.

nun war meine Frage ja : wie "merkt" der "Cache" wenn es neue Daten gibt ?

beim Calender war es einfach den als "Vorgabe" habe ich ein FELD "LastTime". per MAPI kann ich dann an Outlook die "Abfrage" schicken

Code: Alles auswählen

 cFilter     := "[LastTime] >='" + cStart + "' and [LastTime] <= '" + cEnd + "'"
das selbe mache ich nun mit dem "Feld" Lasttime in der DBF ( "C", 18) auf dem ich einen Index TAG habe.

nun habe ich leider nicht in jeder DBF ein FELD "Lasttime" ... und LUpdate() gibt mir ja erst beim "schliessen" der DBF Auskunft ...
mit DbInfo(DBO_*) kann ich ja zur Laufzeit "Informationen" über die DBF erhalten.
in "dmlb.ch"

// Eine Row einer Table wurde verändert
#define DBO_TABLE_UPDATE 5
// Ein Datensatz einer Tabelle wurde gelöscht
#define DBO_TABLE_DELETED 6
// Ein neuer Datensatzw wurde an eine Tabelle angefügt
#define DBO_TABLE_APPEND 7
... aber wie setzte ich das ein :-k
gruss by OHR
Jimmy
Benutzeravatar
Friedhelm
Cut&Paste-Entwickler
Cut&Paste-Entwickler
Beiträge: 46
Registriert: Sa, 08. Apr 2006 17:20
Wohnort: Leverkusen
Kontaktdaten:

Re: DacPagedDataStore vs. Array ?

Beitrag von Friedhelm »

Ich habe mal das Beispielprogramm aus der Doku ein klein wenig geändert um zu zeigen wie die DacPagedDataStore Klasse den Cache aktualisieren kann.
In der Eventloop habe ich die Taste F2 damit belegt einen Datenwert im Array zu verändern. Wenn ich nach dieser Änderung einen Refresh auf die DacPagedDataStore Klasse ausführe, wird dieser Wert direkt in der Anzeige des Quickbrowse übernommen und angezeigt, auch wenn dies nicht der aktuelle Datensatz ist.

Code: Alles auswählen

   #pragma Library( "XppUI2.LIB" )
   #pragma Library( "Adac20b.lib" )
   #include "Appevent.ch"
   #include "Directry.ch"

   PROCEDURE Main
   LOCAL nEvent, mp1, mp2, oXbp

      // The directory array is the data source
      LOCAL aData    := Directory( "*.*" )
      // Array columns to display
      LOCAL aColumns :=    { ;
            F_NAME         , ;
            F_SIZE         , ;
            F_WRITE_DATE   , ;
            F_WRITE_TIME   , ;
            F_CREATION_DATE, ;
            F_CREATION_TIME  }
      // Column headings
      LOCAL aHeader  :=    { ;
            "File name"    , ;
            "File size"    , ;
            "Access date"  , ;
            "Access time"  , ;
            "Creation date", ;
            "Creation time"  }
      oXbp          := XbpQuickBrowse():new(,,, {640,400} )
      // Assign the data store object
      oXbp:dataLink := DacPagedDataStore():new( aData   , ;
                                                aColumns  )
      // Request system resources and assign headers
      oXbp:create()
      oXbp:setHeader( aHeader )
      SetAppFocus( oXbp )
      DO WHILE nEvent <> xbeP_Close
         nEvent := AppEvent( @mp1, @mp2, @oXbp )
         IF nEvent == xbeP_Keyboard
           IF mp1 == xbeK_F2
             aData[1,1] += "."                                        // <= Werteänderung im Array
             oXbp:Datalink:Refresh()                                // <= hier der Refresh auf den Cache
           ENDIF
         ENDIF
         oXbp:handleEvent( nEvent, mp1, mp2 )
      ENDDO
   RETURN
Dieser Refresh() wird nicht auf dem Browser, sondern auf dem Cache ausgeführt

Solltest Du eine eigene (abeleitete KLasse von DacPagedDataStore) schrieben könntest Du diesen Refresh in die Methode GetPos() implizit aufrufen ohne das dein Quickbrowse wackelt oder zuckt.
Gruß Friedhelm
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2824
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: DacPagedDataStore vs. Array ?

Beitrag von georg »

Hallo,


ich stosse auch immer wieder auf diese Klasse, kann mich aber nicht mir ihr anfreunden.

Friedhelm, erst einmal "danke" für Dein Beispiel, das hat mir im Verständnis weitergeholfen, allerdings kann ich daran auch gut mein Problem darlegen:

Wenn ich das Beispiel in einer Demo.prg gespeichert und daraus dann eine Demo.exe erzeugt habe, klappt das alles.

Jetzt ändere ich aber die Datenmanipulation bei F2 wie folgt:

Code: Alles auswählen

aData    := Directory( "demo*.*" )
d.h. ich weise dem Array einen komplett neuen Wert zu, dann ändert sich gar nichts mehr, da innerhalb des Objektes die Referenz auf das alte Array gespeichert ist. Ich suche nun nach einem Weg, ein Array komplett zu ersetzen.

Um den Hintergrund zu erklären: ich überlege derzeit, für einige Programme auf SQLite zurückzugreifen und die Implementierung von Pablo's Seite zu verwenden. Beim ersten SELECT wird ein Array mit den Datensätzen aus dem SELECT zurückgegeben, das ginge als Parameter an die DacPagedDataStore. Wenn ich jetzt das nächste SELECT ausführen, erfolgt in der "Lese"routine (sinngemäss) ein

Code: Alles auswählen

aRec := {}
bevor der erste Satz gelesen wird, damit würde aber auch gleichzeitig die Verbindung zwischen dem DacPageDataStore und meinem Array unterbrochen. Ich suche also nach einem Weg, das Array neu zu beschicken.

Klar kann ich ein iteratives ADel() ausführen, um das Array wieder auf Null zu bringen, aber das halte ich für zeitlich aufwändiger als ein := {}, und ich weiss nicht, wie der Garbage Collector ein solches Vorgehen behandelt.

Aber auch der Versuch, den :datalink auszutauschen, scheitert:

Code: Alles auswählen

         IF mp1 == xbeK_F2
            // aData[1,1] += "."                   // <= Werteänderung im Array
            aData    := Directory( "demo*.*" )
            oXbp:dataLink := DacPagedDataStore():new( aData   , aColumns  )
            oXbp:Datalink:Refresh()             // <= hier der Refresh auf den Cache
         ENDIF



Gruss,

Georg
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Antworten