Alias() Angaben gegen Selectbereich [ERLEDIGT]

Alle Fragen um die Programmierung, die sich sonst nicht kategorisieren lassen. Von Makro bis Codeblock, von IF bis ENDIF

Moderator: Moderatoren

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

Alias() Angaben gegen Selectbereich [ERLEDIGT]

Beitrag von Manfred »

Hi,

bei unserem gestrigen XUG Treffen kam folgender Vorschlag auf den Tisch

Code: Alles auswählen

METHOD datenbank:felderSchreiben(oQuelle,;
                                 lNeuerSatz,;
                                 oZiel,;
                                 lPruefLeer,;
                                 lSchreiben,;
                                 lSatzLoeschen,;
                                 lFelderleeren,;
                                 lDatenBankDirekt,;
                                 lSatzEntsperren,;                             
                                 cProcName,;
                                 nPause,;
                                 lSkip,;
                                 lSpeicherMeldung,;
                                 lKeinZwang)
       LOCAL bArbeit
       LOCAL bSaveError := ErrorBlock( {|e|BREAK(e)})
       LOCAL cArbeit
       LOCAL cFeld
       LOCAL lErfolg        := .T.
       LOCAL nFcount                                                            // darf hier noch nicht belegt werden!!! weil das Zielobjekt hier noch nicht 100% feststeht
       LOCAL nI
//       LOCAL nOldSelect := Select()
       LOCAL oProtokoll := protokolle():new()
       LOCAL oError

       MEMVAR oId
       MEMVAR oSysPara

       DEFAULT oQuelle          TO self                                         // standardmäßig wird die zugehörige DB benutzt
       DEFAULT lNeuerSatz       TO .F.                                          // standardmäßig wird kein neuer Satz angehängt
       DEFAULT oZiel            TO self                                         // standardmäßig wird die zugehörige DB benutzt
       DEFAULT lPruefLeer       TO .T.
       DEFAULT lSchreiben       TO .T.                                          // es wird immer ein Commit dahinter gesetzt
       DEFAULT lSatzLoeschen    TO .F.                                          // Sätze werden normalerweise nicht gelöscht
       DEFAULT lFelderleeren    TO .F.
       DEFAULT lDatenbankDirekt TO .F.
       DEFAULT lSatzEntsperren  TO .T.
       DEFAULT cProcName        TO ProcName(1) + "(" + Alltrim(STr(ProcLine(1))) + ")" // dann wird die aufrufende Routine eingetragen nebst zeile
       DEFAULT nPause           TO 0
       DEFAULT lSkip            TO .F.
       DEFAULT lSpeicherMeldung TO .F.
       DEFAULT lKeinZwang       TO .F.

       ::aTempArray   := {}
       ::nTempZaehler := 0
       nFcount := (oZiel:nArea)->(Fcount())                                     // Zielobjekt abfragen, wieviele Felder es gibt
       IF lNeuerSatz
          IF ! lPruefLeer .OR. ! ::satzRecall(oZiel)                            // normalerweise wird immer zuerst ein leerer Satz genommen und wieder aktiviert
                IF ! ::satzNeu(oZiel,cProcName)                                   // damit kein Fehler entsteht
                   RETURN(.F.)                                                  // erstmal so, später eine elegantere Lösung
                ENDIF
          ENDIF
       ELSE
          IF ! ::satzSperren(oZiel,cProcName,nPause,,lKeinZwang)                // ich hoffe das genügt ohne viel Heckmeck
             lErfolg := .F.
          ENDIF
       ENDIF
       IF lErfolg                                                               // baue ich hier mal ein, wenn keine Sperren mögllich war, dann darf das hier auch nicht durchlaufen werden
          IF lSatzLoeschen
             ::felderleeren()
          ELSE
             IF ! lDatenbankDirekt                                                 // ansonsten würde bei größeren Mengen der Zähler nur hochzählen
                IF oZiel:nIdSatz > 0 .AND. oZiel:id = 0                            // sollte als Zeichen dafür dienen, das auch eine vergeben werden soll
                   IF ! oId:idSpeichern(oZiel)
                      oSysPara:oMessage:anzeigen("ACHTUNG, die Satznummer konnte nicht erzeugt/gespeichert werden. Programmabbruch")
                      AppQuit(,,"ID konnte nicht gespeichert werden")
                   ELSE
                      oZiel:id := oId:id
                   ENDIF
                ENDIF
             ENDIF
          ENDIF
//          Dbselectarea(oZiel:nArea)                                                // weil ja auf jeden Fall ins Ziel geschrieben wird
          FOR nI := 1 TO nFcount
//              cFeld   := (Alias())->(FieldName(nI))
              cFeld   := (oZiel:nArea)->(FieldName(nI))
              IF ::lPruefeDbStrukturArrayAus .AND. ! IsMemberVar(self,cFeld,VAR_INSTANCE)
              ELSE
                 IF lDatenbankDirekt
//                    cArbeit := "{|oQuelle| (Alias())->"+cFeld+" := (oQuelle:nArea)->"+cFeld+"}"
                    cArbeit := "{|oZiel,oQuelle| (oZiel:nArea)->"+cFeld+" := (oQuelle:nArea)->"+cFeld+"}"
                 ELSE
//                    cArbeit := "{|oQuelle| (Alias())->"+cFeld+" := oQuelle:"+cFeld+"}"
                    cArbeit := "{|oZiel,oQuelle| (oZiel:nArea)->"+cFeld+" := oQuelle:"+cFeld+"}"
                 ENDIF
                 bArbeit := &(cArbeit)
                 AAdd(::aTempArray, bArbeit)
              ENDIF
          NEXT
          DO WHILE .T.
             BEGIN SEQUENCE
                   oProtokoll:nMessStart := Seconds()
                   AEval(::aTempArray,{ |b,i|::nTempZaehler := i, Eval( b, oQuelle,  oZiel ) })
                   IF ::lZusatzDbfFelder
//                      (Alias())->usertime := Time() + " - " + DToC(Date())
                      (oZiel:nArea)->usertime := Time() + " - " + DToC(Date())
                   ENDIF
                   oProtokoll:nMessEnde  := Seconds()
                   IF oZiel:nSatzNummer = 0
//                      oZiel:nSatzNummer := (::nArea)->(Recno()) 
                      oZiel:nSatzNummer := (oZiel:nArea)->(Recno())                 
                   ENDIF
             RECOVER USING oError
                   altd()         // der dient der Fehlersuche
                   IF oSysPara:oPruefen:fehlerbehandlung(oError,self)
                      LOOP
                   ENDIF
                   lErfolg := .F.
             END SEQUENCE
             ErrorBlock(bSaveError)
             EXIT
          ENDDO .T.
       ENDIF
       IF lErfolg
          IF lSatzLoeschen
             ::satzSperren(oQuelle,cProcName,nPause)                            // das sollte eigentlich richtig sein.
             (oQuelle:nArea)->(DbDelete())                                      // wenn dann muß doch die Quelle gelöscht werden, die wird doch immer genutzt
          ENDIF
          IF lSatzEntsperren
             ::satzEntsperren(oZiel)
          ENDIF
          IF lSchreiben
             IF lSkip
                (oZiel:nArea)->(DbSkip(0))                                      // evtl. mal testen mit DbGoTop() und wieder zurück zum satz. Soll besser klappen lt. Hubert (11.10.2012)
             ELSE
                (oZiel:nArea)->(Dbcommit())                                     // es gab Probleme bei DELETED() Sätzen. Es wurde dann verkehrt gesprungen bei Skip(0)
             ENDIF
          ENDIF
          IF lFelderleeren                                                      // wenn die Membervars resettet werden sollen
             ::felderleeren()
          ENDIF
          IF lSpeicherMeldung
             IF ! lSatzLoeschen
                oSysPara:oMessage:anzeigen("Satz wurde gespeichert")
             ELSE
                oSysPara:oMessage:anzeigen("Satz wurde gelöscht")
             ENDIF
          ENDIF
       ENDIF
//       DbSelectArea(nOldSelect)
       bArbeit    := NIL
       bSaveError := NIL
       cArbeit    := NIL
       cFeld      := NIL
       nFcount    := NIL
       nI         := NIL
       nOldSelect := NIL
       oProtokoll := NIL
       oError     := NIL
RETURN lErfolg
Ich hatte den Alias() angegeben. Der Vorschlag war statt des Alias den Selectbereich anzugeben, weil dann nicht jedesmal die Alias() Funktion aufgerufen wird und dass sollte eigentlich einen Tempovorteil bringen. Also habe ich es mal so gemacht und die Routine 50000x aufgerufen. Es gab nicht 1 Sekunde Zeitvorteil. das hat uns aber verwundert. Oder liegt ein Denkfehler unsererseits vor?
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
Herbert
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1991
Registriert: Do, 14. Aug 2008 0:22
Wohnort: Gmunden am Traunsee, Österreich
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von Herbert »

sieht man in der PPO-Datei einen Unterschied?
Grüsse Herbert
Immer in Bewegung...
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9355
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von Tom »

Warum sollte ein Unterschied erkennbar sein? Alias und Select-Bereich referenzieren das Workarea-Objekt. Sie tun das m.E. auf sehr ähnliche Weise. Es ist ein paradigmatischer Unterschied, kein großartiger technischer.
Herzlich,
Tom
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von brandelh »

Wenn man bei Millionen von Durchläufen jeweils mit der Funktion ALIAS() den Alias abfragen würde, könnte das etwas langsamer sein, als den Alias direkt bzw. den Selectbereich anzugeben.
Der Aufruf einer Funktion kostet etwas (ms), da aber alles mit Festplattenzugriffen einher geht und diese viel langsamer sind als der Aufruf von Funktionen, auch mit cache, spielt das alles keine Rolle.

Eventuell wenn es auf einer RAM Disk getestet würde ;-)
Gruß
Hubert
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von Jan »

Ich würde ja nicht in jedem Durchlauf den Alias abfragen, sondern den direkt nach dem Öffnen in eine Variable schrieben. Damit ich bei allen weiteren Operationen den immer parat habe.

Oder hab ich da was mißverstanden?

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von brandelh »

Hallo Jan,

mein Beitrag war kein Vorschlag wie man es machen sollte, sondern eine Reaktion auf Manfreds Frage ...
Manfred hat geschrieben: bei unserem gestrigen XUG Treffen kam folgender Vorschlag auf den Tisch ...
Ich hatte den Alias() angegeben.
Der Vorschlag war statt des Alias den Selectbereich anzugeben, weil dann nicht jedesmal die Alias() Funktion aufgerufen wird und dass sollte eigentlich einen Tempovorteil bringen.
... 50000x aufgerufen. Es gab nicht 1 Sekunde Zeitvorteil. das hat uns aber verwundert.
Natürlich schreibt man sich das in eine Variable und nutzt die ;-)
Gruß
Hubert
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von Jan »

Hubert,

das war auch nicht gegen Dich gerichtet. Bei Manfreds Fragestellung kam mir schon der Gedanke.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Herbert
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1991
Registriert: Do, 14. Aug 2008 0:22
Wohnort: Gmunden am Traunsee, Österreich
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von Herbert »

Hubert, nein.
Wie Tom schreibt, die Referenz entscheidet. Wie man dazu kommt ist eigentlich egal.

Manfred, wenn du Optimierungen vornehmen willst, mach das dort, wo entscheidende Zeitgewinne möglich sind
Im Code findet sich immer etwas.
z.B.
- unbenutzte Variablen
- verschachtelte Loops
- unnötige Zuweisungen
- unnötiges Datensuchen
- Code innerhalb Loops
- usw.

Jan, ob du einen Wert aus einen Datenbankfeld oder aus einer Variable holst, macht auch keinen Unterschied. Der Unterschied entsteht erst, wenn du dazwischen in der Tabelle neu positionieren müsstest.
Grüsse Herbert
Immer in Bewegung...
Benutzeravatar
Herbert
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1991
Registriert: Do, 14. Aug 2008 0:22
Wohnort: Gmunden am Traunsee, Österreich
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von Herbert »

Jan hat geschrieben:Ich würde ja nicht in jedem Durchlauf den Alias abfragen, sondern den direkt nach dem Öffnen in eine Variable schrieben. Damit ich bei allen weiteren Operationen den immer parat habe.
Jan, hier kommt noch eine kleine Problematik hinzu: Falls ein anderer User zwischenzeitlich den zwischengespeicherten Wert in der DB ändert, arbeitest du mit dem falschen Inhalt...
Grüsse Herbert
Immer in Bewegung...
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von Jan »

Herbert,

warum und wie sollte ein anderer User den Alias eine dbf ändern (können)?

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Herbert
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1991
Registriert: Do, 14. Aug 2008 0:22
Wohnort: Gmunden am Traunsee, Österreich
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von Herbert »

Ach so, du sprichst vom Alias, nicht vom Inhalt :o
Dann aber die Gegenfrage, warunm du eine Variable brauchst, um einen Aliasbezeichner festzuhalten? Diese Aktion braucht unnötig Zeit und eine unnötige Variable.
Grüsse Herbert
Immer in Bewegung...
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von brandelh »

Herbert hat geschrieben:Ach so, du sprichst vom Alias, nicht vom Inhalt :o
Dann aber die Gegenfrage, warunm du eine Variable brauchst, um einen Aliasbezeichner festzuhalten? Diese Aktion braucht unnötig Zeit und eine unnötige Variable.
Hallo Herbert,

Wenn der ALIAS im Quellcode steht, kannst du den natürlich gleich schreiben ...

Code: Alles auswählen

use Kunde alias KU NEW ...
KU-> ...
Sobald du das so machst und das zweite Fenster (ohne neuen Thread) öffnest, wirst du einen Fehler erhalten, dass der Alias schon benutzt wird, falls du nicht gleich im falschen Datensatz schreibst ...
Daher nutzte ich immer den Select-Bereich, andere speichern den tatsächlichen Alias in einer Variablen und nutzen diese.

Code: Alles auswählen

use Kunde NEW
cAlias := alias() // oder wie ich es mache 
nKunde := select()
(cAlias)-> ...
(nSelect)-> ...
Hubert, nein.
Wie Tom schreibt, die Referenz entscheidet. Wie man dazu kommt ist eigentlich egal.
hast du eigentlich den Thread gelesen ?

PS: unbenutzte Variablen benötigen etwas Speicher, aber keine Zeit ;-)
Gruß
Hubert
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9355
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von Tom »

Ich greife mal ein Stück Code aus Manfreds Beispiel:

Code: Alles auswählen

* Alte Version (auskommentiert):
(Alias())->usertime := Time() + " - " + DToC(Date())
* Neue Version:
(oZiel:nArea)->usertime := Time() + " - " + DToC(Date())
In der alten Version wird über die Alias()-Funktion (!) der Alias ermittelt und dann sofort verwendet. Da diese Funktion sowieso nur in der selektierten Workarea arbeitet bzw. das dazugehörige Ergebnis ermittelt, ist dieser Code redundant und völlig wirkungslos. Er wäre nur dann halbwegs sinnvoll, gäbe es zusätzlich Variablen mit den gleichen Namen wie einige Felder, also "usertime" zugleich als Feld und Variable. Ansonsten entspräche "usertime := Time() ..." exakt dieser Zeile, und es gäbe einen Laufzeitfehler, wäre in diesem Moment keine Tabelle selektiert, und zwar in beiden Varianten, also mit und ohne Alias()-Funktionsaufruf.

"Neue Version" ist aber nicht die direkte Alternative dazu, sondern eine andere Herangehensweise, weil statt des Alias der numerische Selectbereich gewählt wird. Die Information ist aber dieselbe. Der Unterschied besteht darin, dass der Alias oder der Select nicht ermittelt, sondern vorher gespeichert und verwendet werden. Die dritte und tatsächliche Alternative wäre also das hier:

Code: Alles auswählen

(oZiel:cAlias)->usertime := Time() ...
Ob man den Alias beim Öffnen im Datenbankobjekt (oZiel) speichert (weil man ihn ohnehin angibt) oder sich per Alias() holt und dann speichert, macht kaum einen Unterschied. Komplett sinnlos ist allerdings, ihn im Moment des Feldzugriffs zu ermitteln, weil man ohnehin in der fraglichen Workarea unterwegs ist.
Herzlich,
Tom
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von brandelh »

Ich habe das so verstanden, dass es hier darum geht warum kein Geschwindigkeitsunterschied zu bemerken ist.
Sollte tatsächlich die Frage im Raum stehen, was sinnvoller ist, also Alias oder Select Referenzierung, darüber wurde schon viel geschrieben ...

(Alias())-> sehe ich auch als sinnlos an, da kann man einfacher field-> für Felder nutzen und nichts für DBFunktionen.

Der ALIAS selbst hat nur ein Problem und das ist, dass bei mehrfacher Öffnung einer Datei dieser unterschiedlich ausfällt.
Wenn man einen Alias speichert und aufruft, die Datei aber schon geschlossen ist gibt es Laufzeitfehler ... all dies vermeidet man mit dem Zugriff über den Select-Bereich,
dessen Variable den logischen Zusammenhang im Programm darstellt: nKunde enthält den Select-Bereich der Kundendatei etc.

Geschwindigkeitsgründe dürften keine Rolle spielen, da wie schon geschrieben der RAM 1000x schneller ist als selbst die gepufferten Daten einer DBF ... und der Prozessor ist noch schneller.
Ein Programm zu optimieren ist immer sinnvoll, unbenutzte Variablen schaden der Übersichtlichkeit und sollten entfernt werden, aber nicht wegen der Geschwindigkeit.
Gruß
Hubert
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9355
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von Tom »

(Alias())-> sehe ich auch als sinnlos an, da kann man einfacher field-> für Felder nutzen und nichts für DBFunktionen.
"field->" ist nicht einfacher, sondern anders. Und (Alias())-> ist komplett sinnlos, weil die Funktion nur für die aktive Workarea arbeitet, wobei es völlig wurscht ist, ob man einen Alias verwendet oder nicht. Den Alias für die aktuelle Workarea zu ermitteln und in dieser dann zu verwenden, ist, wie beim eigenen Haus nach draußen zu gehen, um zu sehen, welcher Name am Klingelschild steht.
Der ALIAS selbst hat nur ein Problem und das ist, dass bei mehrfacher Öffnung einer Datei dieser unterschiedlich ausfällt.
Das tut er nur, wenn man keinen bei der Dateiöffnung angibt. USE <cTable> ALIAS <cAlias> ordnet "cAlias" als Alias dieser Tabelle und genau dieser Tabelle zu.
Herzlich,
Tom
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9355
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von Tom »

Das Verwendungsbeispiel ist falsch.

Wenn ich je Tabelle ein Datenbankobjekt - nennen wir es "oTabelle" - erzeuge, das eine Instanzvariable "xSelectAlias" kennt, kann ich das belegen, und zwar so:

Code: Alles auswählen

METHOD oTabelle:OpenTable(cTableName)
* Tabelle öffnen
DbUseArea( ... ) // hier kann ich einen Alias angeben, muss aber nicht, weil:
* Ist Tabelle offen? Dann:
* Alias verwenden:
::xSelectAlias := Alias()
* oder Select-Bereich verwenden
::xSelectAlias := Select()
So oder so kann ich anschließend so agieren:

Code: Alles auswählen

(oTabelle:xSelectAlias)->usertime := Time()
Technisch - und auch im Hinblick auf die Ausführungsgeschwindigkeit - dürfte das keinen Unterschied erzeugen. Nahezu nihilistisch ist jedoch "(Alias())->usertime := ..."
Herzlich,
Tom
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von brandelh »

Tom hat geschrieben:
Der ALIAS selbst hat nur ein Problem und das ist, dass bei mehrfacher Öffnung einer Datei dieser unterschiedlich ausfällt.
Das tut er nur, wenn man keinen bei der Dateiöffnung angibt. USE <cTable> ALIAS <cAlias> ordnet "cAlias" als Alias dieser Tabelle und genau dieser Tabelle zu.
Wenn ich mehrere Fenster mit dem gleichen Code erzeuge, kann ich den Alias so nicht festlegen, weil er beim zweiten anders heißen muss - solange man nicht mit Thread trennt.

FIELD-> ist deshalb "einfacher" weil es der Runtime nur klar macht "es wird ein Feld in der aktuellen Workarea angesprochen, keine PRIVATE und keine LOCAL, sondern ein Feld" ;-)
Das ist "einfacher" als mit ALIAS() die DBF der aktuellen Workarea zu ermitteln und dann diese anzusprechen ;-)

Aber ehrlich gesagt ist das Thema so ausgelaugt, dass ich keine Lust habe noch mehr dazu zu schreiben.
Gruß
Hubert
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9355
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von Tom »

Hallo, Hubert.

Ja, "ausgelaugt" ist das richtige Wort. :wink:

Ich muss mir irgendwas merken, wenn es nichts gibt, das ich eindeutig festlegen kann. Wenn eine Funktion, die Tabellen öffnet, mehrfach und im gleichen Thread aufgerufen werden kann, und zwar parallel, funktioniert ein fester Alias natürlich nicht mehr. Ein fester Select-Bereich sowieso nicht. Also muss ich die Tabelle öffnen und mir anschließend eines von beidem merken, aber was das von beidem ist, das ist letztlich wurscht. Also erzeuge ich ein Objekt oder eine lokale Variable, in der ich eines von beidem direkt nach der Dateiöffnung speichere. Wenn ich anderswo sicher sein kann, dass die richtige Tabelle selektiert ist, kann ich dort Alias() oder Select() verwenden, um die Information zu ermitteln. Wenn die Tabelle sowieso selektiert ist, wie in der FCount()-Schleife in Manfreds Code, brauche ich beides eigentlich nicht. Aber es ist auf Feldebene nicht sehr sinnvoll, die Ermittlung zu versuchen, weil sie vorher nötig wäre.
Herzlich,
Tom
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21186
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Re: Alias() Angaben gegen Selectbereich

Beitrag von Manfred »

Uihuihuih

mal wieder ins Schwarze getroffen. Es ging "uns" nur darum, das vermutet wurde, es würde schneller werden, nicht jedesmal die Alias() Funktion anzugeben.

Außerdem ist dieser Bereich auf Huberts Mist gewachsen, er hat das damals erarbeitet, als ich zum ersten Mal die Frage dazu stellte. Nur damals ging es um Privat Variablen und er hatte das auf LOCAl umgebaut. Temposache war das damals.

Das es so gelöst ist, wie es ist hat folgenden Grund: Diese Methode erlaubt es alle Varianten zu verknüpfen. Man kann durch die Angabe von Ziel und Quelle egal mit welcher Datenbankklasse von beliebiger DBF in beliebige DBF schreiben oder eben in die, die zur Klasse gehört, wenn nichts angegeben wird. Über Membervariablen, oder direkt von DBF nach DBF. Aber eigentlich ging es hier nur noch um das Tempo und da war Andreas am Samstag feste der Meinung, es müßte sich was tun. Was es aber nicht tat. Nur hatte ich mir damals auch nicht genau angesehen, was ich da für Möglichkeiten eingebaut hatte, sonst hätte ich mir das mit dem DbSelectArea() auch schenken können, das war eigentlich der Hauptgrund, bei dem auch vermutete würde, dass es Zeit kostet. . Tja, wieder dazu gelernt.
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
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9355
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von Tom »

Nach meiner ganz subjektiven und nie wirklich nachgemessenen Erfahrung kostet ein DbSelectArea() tatsächlich Zeit - mehr Zeit als der Zugriff auf Felder mit einem Aliasoperator.

Das hier:

Code: Alles auswählen

? db->name
? db->vorname
ist, eine entsprechende Umgebung vorausgesetzt, demnach tatsächlich schneller als

Code: Alles auswählen

select db
? name
? vorname
select xy
Signifikant wird es unter solchen Bedingungen:

Code: Alles auswählen

select ab
DbSetScope(SCOPE_BOTH,<xyIrgendwas>)
select cd
DbSetScope(SCOPE_BOTH,<xyIrgendwas>)
Besser:

Code: Alles auswählen

ab->(DbSetScope(SCOPE_BOTH,<xyIrgendwas>))
cd->(DbSetScope(SCOPE_BOTH,<xyIrgendwas>))
Das liegt vor allem daran, dass (hier) der Scope Bedingungen formuliert, die im Moment der Formulierung noch überhaupt keine Wirkung haben, weil der Scope-Ausdruck erst evaluiert wird, wenn die erste Navigation in der Tabelle stattfindet. DbSelectArea() oder SELECT jedoch aktivieren die fragliche Workarea als die derzeit gültige, schaufeln also vermutlich intern ein bisschen was an Daten hin und her, belegen Get-Set-Funktionen usw. All das ist unnötig, weil es nicht gebraucht wird - man will ja nur eine Bedingung für die nächste Navigation in dieser Workarea definieren. Vermutlich verhält es sich bei anderen Operationen ähnlich. DbSelectArea() ist nett, weil man sich keine Gedanken über Aliase und ähnliches machen muss, wenn man Zugriffe formuliert, aber sehr wahrscheinlich - jedenfalls nach meinem Dafürhalten - geschieht bei genau dieser Funktion einiges mehr als nur das Setzen irgendeines Parameters, der bei den folgenden Operationen verwendet wird. Wie gesagt - sehr subjektiv und nie wirklich nachgemessen.

Allerdings steht in der Referenzdoku von Xbase++ das hier:

Der Alias-Operator impliziert in diesen Fällen den Befehl SELECT, der eine Workarea auswählt. Nach der Auswertung des Ausdrucks auf der rechten Seite des Operators wird die ursprüngliche Workarea wieder als aktuelle ausgewählt.

Wenn das wirklich so ist, wäre das gefühlte Verhalten tatsächlich nur ein gefühltes. Ich bin aber tatsächlich der Meinung, dass eine Änderung eintritt.

Edit: Das Beispiel mit den Scopes ist unglücklich bzw. falsch gewählt, da sich Scopes tatsächlich direkt beim Setzen auswirken, also sofort eine Änderung des Satzzeigers eintritt. Es ist - im Gegensatz zu Filtern beispielsweise - kein anschließendes DbGoTop() nötig.
Herzlich,
Tom
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21186
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Re: Alias() Angaben gegen Selectbereich

Beitrag von Manfred »

ok, in diesem Fall hat Dbselectarea() nichts verlangsamt. Es wurde ja auch entfernt hatte aber letztendlich dann keinen Nachteil bewirkt.
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
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von brandelh »

Tom hat geschrieben:Nach meiner ganz subjektiven und nie wirklich nachgemessenen Erfahrung kostet ein DbSelectArea() tatsächlich Zeit - mehr Zeit als der Zugriff auf Felder mit einem Aliasoperator.
Das hier:

Code: Alles auswählen

? db->name
? db->vorname
ist, eine entsprechende Umgebung vorausgesetzt, demnach tatsächlich schneller als

Code: Alles auswählen

select db
? name
? vorname
select xy
Die Aussage zur Geschwindigkeit habe ich nicht geprüft, ist für mich zu dem Thema aber weniger wichtig, wie die Sicherheit des Codes.
Wie schnell kommt man mit der ersten Schreibweise durcheinander und hat dann doch ein Feld in der falschen DBF angesprochen oder man will ein Feld mit dem Inhalt aus einer anderen DBF füllen ...

Mit der direkten Schreibweise wird das alles erledigt (und schneller mag es auch sein) und zwar für alle Zeiten sofort ersichtlich klar und deutlich.

Code: Alles auswählen

// Am Anfang DBFs öffnen und auf NETERR() testen ...
use (cKunden) alias KU NEW ...
if neterr()...
use (cRechnung) alias RE NEW ...
if neterr()...
...
// Dann eine Schleife oder Positionieren wie man es braucht ...
do while ! RE->(eof())
   KU->(dbSeek( RE->KuNr )) 
   if RE->offen
      ...
      // irgendwelche Zugriffe ...
      ? KU->NAME, RE->ReNr, ...
   ...
   KU->(dbSkip())
endo
...
wer das so schreibt, erleichtert sich und anderen das Leben und in 10 Jahren kann jeder Entwickler am code sicher Anpassungen vornehmen.
Das ist der Vorteil der direkten Schreibweise, eventuelle Geschwindigkeitsvorteile nimmt man dann gerne noch mit ;-)

PS: noch lieber wären mit statt der ALIAS-> oder (nSelect)-> oder (cAlias)-> gleich dbServer Objekte, wie es sie bei VO gab, aber man kann nicht alles haben ;-)
Vermutlich ist das Manfreds Ansatz ... und ja, mein Beispiel ist eventuell nicht sinnvoll, aber es ging mir um die Schreibweise und es wurde schnell heruntergetippt. 8)
Gruß
Hubert
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21186
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Re: Alias() Angaben gegen Selectbereich

Beitrag von Manfred »

Nochmals,

1) Hubert es sollte auf keinen Fall eine Kritik an Deine Arbeit sein, Du hast mit dem Vorschlag damals sehr geholfen.
2) Es sollte auf keinen Fall eine Frage des sauberen Programmierens sein, ich arbeite an keiner Stelle in meinen Programmen ohne Dateinamenangabe, bzw. Selectbereich
3) Es ging lediglich um eine Stelle, die ich übersehen hatte und bei der vermutet wurde, dass es eigentlich auch "wesentlich" schneller sein sollte, wenn man es "sauber" macht.

Das es dann doch nicht so war, ist halt interessant, aber eben so gegeben
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
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Alias() Angaben gegen Selectbereich

Beitrag von brandelh »

warum macht Ihr euch alle soviel Sorgem um Kritik an mir ;-)
dass es eigentlich auch "wesentlich" schneller sein sollte, wenn man es "sauber" macht.
Das es dann doch nicht so war, ist halt interessant, aber eben so gegeben
Ich hatte ausschließlich den 3. Punkt auf der Liste als ich meine Antworten in diesem Thread schrieb ;-)
Gruß
Hubert
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: Alias() Angaben gegen Selectbereich

Beitrag von AUGE_OHR »

Manfred hat geschrieben:

Code: Alles auswählen

          FOR nI := 1 TO nFcount
...
                 IF lDatenbankDirekt
                    cArbeit := "{|oZiel,oQuelle| (oZiel:nArea)->"+cFeld+" := (oQuelle:nArea)->"+cFeld+"}"
                 ELSE
                    cArbeit := "{|oZiel,oQuelle| (oZiel:nArea)->"+cFeld+" := oQuelle:"+cFeld+"}"
                 ENDIF
                 bArbeit := &(cArbeit)
                 AAdd(::aTempArray, bArbeit)
              ENDIF
          NEXT

          DO WHILE .T.
             BEGIN SEQUENCE
                   oProtokoll:nMessStart := Seconds()
                   AEval(::aTempArray,{ |b,i|::nTempZaehler := i, Eval( b, oQuelle,  oZiel ) })
Frage :
wie lange dauert eine Schleife mit dem &(cArbeit) ?
warum sammelst du du erst um die dann auszuführen ?
werden immer alle Felder geändert ?
gruss by OHR
Jimmy
Antworten