Mehrere Scopes?

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

Moderator: Moderatoren

Antworten
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Mehrere Scopes?

Beitrag von Jan »

Besteht die Möglichkeit, mehrere Scopes auf eine Datenbank zu setzen?

Ich habe das so versucht, daß ich den betreffenden Index wähle, den Scope setze, den nächsten Index wähle und auch hier den Scope setze. Aber das funktioniert nicht. Der 1. Scope wird anscheinend mit Setzen des 2. verworfen.

Gibt es da eine Lösung? Ich hoffe sehr, denn ich würde da gerne einige Filter mit loswerden, die einfach zu langsam sind.

Aber grundsätzlich: Ich verstehe das schon richtig daß ein Scope nur bei einem Index auf dem betreffenden Feld eingesetzt werden kann?

Jan
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Beitrag von Tom »

Hallo, Jan.

Ein Scope funktioniert im Prinzip wie ein Filter; der einzige generelle Unterschied besteht darin, daß Indexausdrücke herangezogen werden. Deshalb kann es auch nur einen je Workarea (!) geben. Wenn Du zwei Scopes auf die selbe Tabelle setzen willst, dann mußt Du sie (einfach) ein zweites Mal parallel öffnen. Das kannst Du im Prinzip beliebig oft tun.
Herzlich,
Tom
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hallo Jan,

ein Scope ist ein Filter auf den Indexausdruck.
Man kann aber leicht einen scope mit einem filter kombinieren.
Der Filter ist flexibler, der Scope schneller.
Somit musst du den Index so aufbauen, dass erstens die Sortierung stimmt und zweitens die Anzahl der Datensätze deutlich reduziert wird.
Nun noch den Filter dazu, der dann ja nur noch die Sätze im Scope Bereich durchsuchen muss und du bist schnell und flexibel:

Beispiel:

Filter auf PLZ+Name+Vorname ... bei 1000000 Datensätzen, indiskutabel ...
Scope auf PLZ+Namensteil ... wenn man Glück hat bleiben nur wenige (bis einige hundert) Datensätze.
nun Filter auf Vornamensteil, bei einigen 100 kein Problem.

Wenn man aber nur flexible Treffer im Index suchen will, z.B.
PLZ + Teilnamen aber nicht linksbündig, kann man auch den neuen
Befehl ordwildseek nutzen (Index selbst bleibt gleich) jeder Aufruf bringt den nächsten Treffer. Sehr schnell, eventuell Index erweitern, muss nicht linksbündig suchen.
Im Beispiel z.B. suche nach '67322*Elke' findet alle Elkes im Ort, wenn der Indexbegriff PLZ+Name+Vorname lautet.
Wenn man diese Ergebnisse allerdings browsen möchte, muss man ein Array mit Satznummern füllen und die Anzeige dann jeweils auf goto(recno(())) zwingen. Das habe ich noch nicht gemacht.
Gruß
Hubert
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Beitrag von Jan »

Hallo Hubert und Tom,

verstanden. Wenn auch ärgerlich, ich hatte mir das jetzt so schön gedacht.

Habt Ihr vielleicht eine Idee, wie ich das Problem lösen kann? Es geht da um folgendes:

Datenbank mit den Auftrags-Kopfdaten wird gebrowsed. Relationen bestehen zu den Verkäufernamen (werden im Browse in jedem Datensatz angezeigt), zu den Adressen (da könnte ich vielleicht tricksen und das entfernen) und zu den Anzahlungen. Dabei kann man folgende Filter per XbpCombobox einstellen:
Auftragsstatus: Aktuell (Standard), Archiv, beides, oder Gibt es neue Anzahlungen auf den Auftrag
Verkäufer: Alle (Standard) oder einen bestimmten auswählen

Und da gibt es dann natürlich alle möglichen Variationen. Die ich natürlich gerne flott im Browse aktualisieren möchte. Das geht als dbf übers Netz mit z. Zt. gut 20.000 Datensätzen. Dauert mit "normalem" Filter mehrere Sekunden, bis sich das aufgebaut hat. Das ist beim Öffnen der Oberfläche schon schlimm benug, beim Blättern aber absolut indiskutabel.

Jan
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Beitrag von Tom »

Hallo, Jan.

Da Martin unvermeidlicherweise sowieso mit diesem Vorschlag kommen wird ;-) - es scheint mir tatsächlich am einfachsten, die vom Auftragskopf abhängigen Daten in Arrays zu sammeln. Sobald also der Zeiger in der Auftragsdatei bewegt wird, sammelst Du die abhängigen Daten in Arrays, zunächst alle. Und je nach Einstellung in den Auswahlboxen erzeugst Du aus den Arrays Klone, die nur die "gefilterten" Daten enthalten. Wenn die Auswahl geändert wird, ensteht ein neues geklontes Array aus dem Ursprungsarray. Die Zeit, die zum Zusammenstellen der Daten benötigt wird, dürfte gering sein (Scope auf Auftragsnummer), und danach geht es ratzfatz. Für die Verfügbarkeit der echten Daten nimmst Du die jeweilige RecNo() in das Array, DbGoto() - fertig.
Herzlich,
Tom
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hallo Jan,

ich würde die Relationen durch manuelles setzen von scopes etc. ersetzen.
1. habe ich überhaupt schlechte Erfahrungen mit Relationen und automatischem Verhalten ...
2. könnte durch scope und relation eine Art Rückkopplung entstehen.

Bei jeder Satzbewegung in der Hauptdatei prüfst du ob der Schlüsselbegriff in den Kinddaten geändert wurde.
Wenn ja, neuen scope in den Kinddateien setzen, eventuell zusätzliche Filter und die Browser neu einlesen lassen. Wenn die Daten statisch sind, können Arrays zum Puffern nützlich sein (mit genug RAM sind 20000 Einträge im Array je 100 Byte kein Problem).
Beim Browser müsste man das nachführen der Kinder darauf einschränken, dass die Anzeige stable ist um interne skips nicht mitzuführen.
Wenn der Quickbrowse reicht, diesen nutzen, der ist in Verbindung mit den DacPagedDataStore() wesentlich schneller im Aufbau und der Anzeige.
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hi Jan,

zu den Verkäufernamen fällt mir ein ...

die sind ja bestimmt recht statisch.
Ich habe häufig bei mir Hilfstabellen, deren Werte ich beim ersten Programmstart in einer Funktion (static var) zwischenspeichere.
In deinem Fall könnte eine Funktion in dieser Art nützlich sein:

Code: Alles auswählen

vorher schon offen Verkäuferdatei alias VK
im browser... getVerkInfo(stamm->VK_ID,"N") ...

function getVerkInfo(cVK_ID,cFeld)
    static aVKINFO := {}
    local x:=0, cReturn := ""
    x := ascan(aVKINFO, Suchcodeblock je nach Arrayart nach cVK_ID)
    if x = 0 // VK in Datei suchen
       if VK->(dbseek(cVK_ID))
          aadd(aVKINFO, {.....}) // Name oder mehr Infos
          if cFeld="N"  // oder mehr ??
             cReturn := VK->NAME
          endif 
       else
          // Fehlermeldung ... wie man es will ?
          aadd(aVKINFO, {.....}) // auch Fehler speichern ????
          cReturn := "???"
       endif
    else
       if cFeld="N"  // oder mehr ??
          cReturn := aVKINFO[x,nFeldName] // nFeldName sollte man über #DEFINE benennen
       endif 
    endif
return cReturn       

          
Eventuell kann man so mehrere Felder dynamisch bis zum nächsten Programmstart zwischenspeichern und Plattenzugriffe verringern.
Zuletzt geändert von brandelh am Fr, 08. Dez 2006 17:15, insgesamt 1-mal geändert.
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

du schreibst weiterhin, dass im Netzwerk mit mehreren Anwendern laufen muss. Hier kann der Lesezugriff (= browsen) durch das extended locking der CDX erheblich beschleunigt werden.
Zumindest laut dem Vortrag der letzten devcon den ich gestern auf dem STICK gelesen habe.
Gruß
Hubert
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Beitrag von Jan »

Hubert,

nur eben schnell einer Deiner Punkte: Die Geschichte mit den Relationen. Ich bin selber auch überhaupt kein Freund davon. Wo immer es geht schmeiß ich die raus.

Nur: Ich bin noch nicht dahinter gekommen, wie ich ohne Relation einen Browse über mehrere Datenbanken bewerkstelligen soll. In diesem Fall ist es so, daß in den Auftrags-Kopfdaten nur die Verkäufernummer hinterlegt ist. Im Browse soll aber der Name erscheinen. Deswegen die Relation darauf. Und die "Neuen Zahlungen" auf den Auftrag werden ebenfalls in einer eigenen Datenbank verwaltet. Da ich auch hierauf filtern muß (die Verkäufer sollen eine Übersicht erhalten, wo es Zahlungen gibt, welche Aufträge damit zur verarbeitung anstehen), gibt es hierüber ebenfals eine Relation.

Abhängge Daten gibt es sonst nicht. Der Browse soll einfach nur einen Überblick geben. Sollen etwa die Positionen dieses Auftrages bearbeitet werden, so geschicht das in einem extra zu öffnenden Browse, wo dann die entsprechenden Datenbanken geöffnet werden, gefiltert um die entsprechende Auftragsnummer.

Jan
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21165
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 206 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Hi Jan,

ich habe auch noch keine Ahnung, wie man das in einem Browse einbaut. Ich weiß aber, dass Jimmy es mal erklärt hat, finde es aber nicht mehr wieder.
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
Rolf Ramacher
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1930
Registriert: Do, 09. Nov 2006 10:33
Wohnort: Bergheim
Danksagung erhalten: 3 Mal
Kontaktdaten:

Index suchen

Beitrag von Rolf Ramacher »

Hallo Jan,

ich mache dies immer folgendermaßen

meistens habe ich dies beim start des Main-Programms das Indexdateien
festgelegt werden.

Index on xxx tag "xxxx" to ">name der index-Datei>.cdx"

beim bearbeiten nachher in den Programmroutinen nach dem use
set index to ">name der index-Datei>.cdx"

name der Datenbank ordsetfocus(>tagname<)

Hierbei kannst du mehrere Indexsortierungen in einer cdx-Datei gestalten.
Gruß Rolf

Mitglied der Gruppe XUG-Cologne
www.xug-cologne.de
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hallo Jan,

habe ich dich richtig verstanden, dass du in einem XbpBrowse() mehrere DBFs anzeigst ?
Dann ist das schwieriger. Ich vermute du müstest dann den skipblock() oder den datalink() der Spalte anpassen. Aber ob es wirklich besser wäre als dein relation weiß ich auch nicht.
Gruß
Hubert
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21165
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 206 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Hi Hubert,

die Frage verwundert mich jetzt aber doch. Wie willst Du ein relationales Db System sonst verwalten? Es müssen doch in einem Browse Verknüpfungen angezeigt werden. Wie willst Du sonst z.B. Aufträge, Lieferscheine oder Rechnungen anzeigen? Es muß Verknüpfungen untereinander geben. Oder habe ich Dich jetzt falsch verstanden? Es ging doch um Spalten aus verschiedenen Tabellen parallel in einem Browse?
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
Rolf Ramacher
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1930
Registriert: Do, 09. Nov 2006 10:33
Wohnort: Bergheim
Danksagung erhalten: 3 Mal
Kontaktdaten:

xbpbrowse

Beitrag von Rolf Ramacher »

Hallo Jan,

du kannst ja auch mehrere Browse in einem Fenster anzeigen. Das Fenster muß nur groß genug sein. Dann brauchst du nur die browse mit der entsprechenden Größe zu positionieren.

Wenn du nur einen Browse erzeugen willst, und du hast Info aus mehreren Datenbanken, so erzeuge doch eine temporäre Datenbank, in der du Informationen zusammenträgst und dann die temporäre Datenbank in den browse zur Anzeige bringst.
Gruß Rolf

Mitglied der Gruppe XUG-Cologne
www.xug-cologne.de
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hallo,

ich habe in solchen Fällen tatsächlich eine Auswahl von Kunden (ein Kunde), einen für Rechnungsstammdaten (mehrere pro Kunde, aber nur einen pro Rechnung), ein weiteres für Rechnungspositionen (viele pro Rechnung) etc.

Man muss halt aufpassen, dass man keine wechselseitigen Abhängigkeiten erzeugt, sonst flippt der Browser nur noch. Aber das ist eigentlich bei Relationen immer so.

Wenn der Browser nur anzeigt, sollte man auf jeden Fall den Quickbrowse nehmen, der puffert die Daten zwischen und ist schneller.
Gruß
Hubert
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Beitrag von AUGE_OHR »

hi,
Manfred hat geschrieben: ich habe auch noch keine Ahnung, wie man das in einem Browse einbaut. Ich weiß aber, dass Jimmy es mal erklärt hat, finde es aber nicht mehr wieder.
Also im Prinzip baut man so ein Browse aus verschiedenen kompletten
(incl. Skipblock) Browse Objecten zusammen.

Code: Alles auswählen

FUNCTION BrowseIt()
   LOCAL aoBrowse := ARRAY(3)
...
   // set up browse and display it
   aoBrowse[1] := KRED1Browse()
   aoBrowse[1]:goTop()
   DispBrowse(aoBrowse[1])

   // set up browse and display it
   aoBrowse[2] := ARTQ2Browse()
   aoBrowse[2]:goTop()
   DispBrowse(aoBrowse[2])

   // set up browse and display it
   aoBrowse[3] := ABZU3Browse()
   aoBrowse[3]:goTop()
   DispBrowse(aoBrowse[3])
...
jedes Object wird also in ein Array aufgenommen.
Der "Witz" liegt nun in der "umschaltung" der Objecte :

Code: Alles auswählen

   // set browse pointer to first browse defined
   nBP := LEN(aoBrowse)
   DispBrowse(aoBrowse[nBP])

   nBP := 1                                     // start with first window
   // main browse display loop
   lMore := .T.
   DO WHILE lMore
      nKey := 0
      // Stabilize the browse until it's stable or a key is pressed
      DO WHILE (nKey := INKEY()) == 0 .AND. !aoBrowse[nBP]:stabilize()
      ENDDO

      IF aoBrowse[nBP]:stable
         // alert if hit top or bottom of browse
         IF aoBrowse[nBP]:hitTop .OR. aoBrowse[nBP]:hitBottom
            TONE(125, 0)
         ENDIF

         // update other browse screens in case relations are set
         IF !EMPTY(DBRELATION(1))
            DrawAll(aoBrowse, nBP)
         ENDIF

         aoBrowse[nBP]:hilite()

         // Get a new keystroke
         nKey := INKEY(0)
      ENDIF

      // Apply the key to the browse
      lMore := ApplyKey(aoBrowse, nKey, @nBP)
   ENDDO
wie man sieht gibt es einen "Zähler nBP". Der muss auch immer in
ApplyKey mit berücksichtigt werden.

Code: Alles auswählen

FUNCTION ApplyKey(aoBrowse, nKey, nBP)
   LOCAL lMore := .T.

   DO CASE
      CASE nKey == 5  ; aoBrowse[nBP]:up()       // Up-arrow
      CASE nKey == 24 ; aoBrowse[nBP]:down()     // Down-arrow
...
      CASE nKey == 27 ; lMore := .F.             // Esc
      CASE nKey == 13                            // Enter
         DoGet(aoBrowse[nBP]) ; aoBrowse[nBP]:refreshCurrent()

      CASE nKey == K_TAB
           nBP++
           IF(nBP>3,nBP:=1,NIL)
   ENDCASE
   RETURN lMore
In diesem Beispiel hab ich noch "Relationen". Wenn also "IF !EMPTY
(DBRELATION(1))" erfüllt ist wird ein "DrawAll" durchgeführt.

Code: Alles auswählen

FUNCTION DrawAll(aoBrowse, nBP)
   LOCAL n
...
   FOR n := 1 TO LEN(aoBrowse)
      IF n != nBP
         DispBrowse(aoBrowse[n])
      ENDIF
   NEXT
   DispBrowse(aoBrowse[nBP])
...
   RETURN (NIL)

// Display the browse screen
FUNCTION DispBrowse(oBrowse)

   // select the database for this browse
   SELECT (oBrowse:cargo[ALIAS])
...
   // clear old screen area
   @ oBrowse:cargo[BOXTOP], oBrowse:cargo[BOXLEFT] CLEAR TO oBrowse:cargo[BOXBOTTOM], oBrowse:cargo[BOXRIGHT]

   // display the browse box
   DISPBOX(oBrowse:cargo[BOXTOP], oBrowse:cargo[BOXLEFT],;
      oBrowse:cargo[BOXBOTTOM], oBrowse:cargo[BOXRIGHT],;
      oBrowse:cargo[BOXTYPE], oBrowse:cargo[BOXBORDER])

   // refresh browse so all data is redisplayed in the box
   oBrowse:refreshAll()
   ForceStable(oBrowse)
...
   RETURN (NIL)
Da wir nur "bestimmte" Datensätze haben wollen müssen wir auch die
"Skipper" anpassen auf die "bWhileCond"

Code: Alles auswählen

STATIC FUNCTION GoNext(nToSkip, bWhileCond )
   LOCAL nSkipped := 0, nDirection
   nDirection := IIF(nToSkip > 0, 1, -1)
   DO WHILE nSkipped != nToSkip .AND. EVAL(bWhileCond) .AND. ;
     !EOF() .AND. !BOF()
      SKIP nDirection
      nSkipped += nDirection
   ENDDO
   IF EOF()
      SKIP -1
      nSkipped--
   ELSEIF BOF()
      GOTO RECNO()
      nSkipped++
   ELSEIF !EVAL(bWhileCond)
      SKIP -nDirection
      nSkipped += -nDirection
   ENDIF
   RETURN nSkipped

STATIC FUNCTION GoTop( bWhileCond )
   WHILE EVAL( bWhileCond ) .AND. !BOF()
      SKIP -1
      IF !EVAL( bWhileCond )
         SKIP
         EXIT
      ENDIF
   END
   RETURN (NIL)

STATIC FUNCTION GoBottom( bWhileCond )
   WHILE EVAL( bWhileCond ) .AND. !EOF()
      SKIP
   END
   // We always skip 1 too far, so skip back
   SKIP -1
   RETURN (NIL)
So damit müsste man alle "Bausteine" für ein "Multi-browse" haben.

gruss by OHR
Jimmy
Antworten