1

In select-Abfrage funktioniert 'this' als Referenz nicht ?

Wir lernen ja, dass wir die Performance steigern können, wenn wir z.B. Select-Abfragen in 'do as transaction' kapseln. Offensichtlich wird die Abfrage dann schneller ausgeführt.

Nun wollte ich das anwenden bei einer Select-Abfrage, die als Code in einer Dynamischen-Auswahl zugrunde liegt:

let zz := this;
(select Vorgabewerte where Typ = 6 and Name = "Auftragsstatus" and contains(Textblock, text(zz.Auftragstyp))) order by Zahl

wenn ich die Abfrage nun so ändere dass ich nicht 'zz' als Referenz verwende sondern 'this' - dann schlägt der Code mit einem Fehler an, dass er this.Auftragstyp nicht kennt.
 

do as transaction select Vorgabewerte where Typ = 6 and Name = "Auftragsstatus" and contains(Textblock, text(this.Auftragstyp)) order by Zahl end

Und das liegt nicht an der transactionk, auch ohne wird es als falsch gemeldet:
 

select Vorgabewerte where Typ = 6 and Name = "Auftragsstatus" and contains(Textblock, text(this.Auftragstyp)) order by Zahl

Bedeutet das nun, dass man in select-Abfragen nicht auf 'this' referenzieren kann ?

11 Antworten

null
    • mirko3
    • vor 4 Monaten
    • Gemeldet - anzeigen

    Hallo Dirk. Ich verstehe es so, dass das this, sich jeweils auf die Umgebung bezieht. Deklarierst du eine Variable wie in let me:= this, dann bezieht es sich auf die Tabelle in der du das Script schreibst. Benutzt du es aber in einer Selectanweisung, dann ist diese Tabelle die Umgebung und this (= record() der Tabelle Vorgabewerte) ist nutzlos, da es das Feld Auftragstyp wahrscheinlich in der Tabelle Vorgabewerte nicht gibt. Deshalb das Deklarieren einer Variablen in der Ausgangstabelle, dann kannst du diese Variable "mitnehmen" in die andere Umgebung der Selecttabelle. Mirko

      • Dirk_Pulver
      • vor 4 Monaten
      • Gemeldet - anzeigen

      Ok, aber moment - du sagtest ...dann kannst du diese Variable "mitnehmen ... nach meinem Kenntnisstand kann ich außerhalb einer [do as] Funktion definierte Variablen nicht innerhalb dieser Sektion verwenden.  Also wenn ich zuvor let me := this deklariere kann ich doch innerhalb von [do as transaction] nicht auf 'me' zurückgreifen  ? D.h. ich müsste noch innerhalb der [do as transaction] Funktion zuerst die me-Variable deklarieren....

      Bsp:
       

      let a :=  do as transaction
        let me := this;
        select Tabelle where Feld = me.Suchwert
      end;
      

      Das erschiene mir logisch.

      • mirko3
      • vor 4 Monaten
      • Gemeldet - anzeigen

       Wenn eine Variable in oberster Hirarchieebene deklariert wird, ist sie global, kann überall benutzt werden. Wird sie in einer Umgebung deklariert, dann ist sie nur in dieser sichtbar.

      In Deinem Beispiel kann me ausserhalb von do as...end nicht benutzt/gesehen werden. Deklarierst du sie oberhalb von do as...end, dann steht sie zwangsläufig auch innerhalb von do as...end zur Verfügung. Mirko

      • Dirk_Pulver
      • vor 4 Monaten
      • Gemeldet - anzeigen

      Leider stimmt das nicht. Wenn ich eine Variable außerhalb von [do as server] deklariere, funktioniert sie innerhalb eben nicht und umgekehrt! Das würde das Leben bedeutend einfacher machen....

      • mirko3
      • vor 4 Monaten
      • Gemeldet - anzeigen

       interessante Diskussion. Vielleicht auf der Basis von Missverständnissen;-). Meine These: globale Variable in do as…end nutzbar, Variable innerhalb von do as…end angelegt ist ausserhalb nicht nutzbar. Anbei eine Test DB, die diese Ergebnisse belegt. Mirko

    • Ninox-Professional
    • planoxpro
    • vor 4 Monaten
    • Gemeldet - anzeigen

     said:
    Bedeutet das nun, dass man in select-Abfragen nicht auf 'this' referenzieren kann ?

    Das war m. W. schon immer so. "this" bezieht sich ja auf die aktuell geöffnete Tabelle, und mit dem "select" setzt Ninox den Fokus auf die dort referenzierte Tabelle, womit der Bezug verloren geht. Deshalb sieht man das "me := this" so oft am Anfang von Scripten.

    Mit den Variablen bei serverseitig auszuführendem Code ist es, glaube ich, folgendermaßen: Vor dem "do as server" definierte Variablen können innerhalb "do as server" genutzt werden. Variable, die im "do as server" definiert werden, lassen sich jedoch nicht außerhalb des do-as-Blocks nutzen.
     

      • Dirk_Pulver
      • vor 4 Monaten
      • Gemeldet - anzeigen

      Ok, man hört immer so viel "... glaube ich ..." - meine Erfahrung ist dass beides nicht funktioniert. Variable hineingeben oder herausholen. Aber ich teste das nochmal genauer - vielleicht hatte ich bisher immer nur den falschen Fall. Seit vorgestern weiß ich nur, dass die [do as] scripte einen Rückgabewert ausspucken, den man abgreifen kann - also let a := do as server select.... end. Aber wenn ich eben z.B. in der select-Abfrage eine Variable oder ein Feld verwende, welches vorher schon definiert wurde, wird's eben schwierig.

      • Ninox-Professional
      • planoxpro
      • vor 4 Monaten
      • Gemeldet - anzeigen

       

      Hallo Dirk, ich gebe Antworten hier nach bestem Wissen und Gewissen, wie man so schön sagt, nutze dabei aber oft den Konjunktiv um zu verdeutlichen, dass ich natürlich auch mal falsch liegen kann. Generell, aber auch, weil es erfahrungsgemäß Konstellationen und Faktoren geben kann, die zu einem anderen Ergebnis führen.

      Was ich sicher sagen kann ist, dass bspw. folgender Code bei mir funktioniert:

      let me := this;
      let myValue := Datenfeld;
      do as server
         me.(Ergebnis := first(select Tabelle where Feld1 = myValue).Feld2);
      end

      Daraus folgt: Ja, man kann zuvor definierte Variable im "do as server" nutzen.

      Versuche ich hingegen, eine im "do as server" definierte Variable nach dem "end" zu nutzen, bekomme ich schon im Editor eine Fehlermeldung (siehe Screenshot).

      Dritte Variante: Variable wird vorher definiert, im do-as-server-Block verändert und danach angesprochen. Dabei gibt es keine Fehlermeldung im Editor, der Wert von myX bleibt "false", es wird aber auch die Zeile "me.(Ergebnis := ..." nicht ausgeführt.

      let me := this;
      let myDate := Datum;
      let myX := false;
      do as server
         me.(Ergebnis := first(select Auditplan where Datum = myDate).Text);
         myX := true
      end;
      alert(myX)

      Jetzt versuche mal, daraus eine sichere, verbindliche Aussage zur Gültigkeit von Variablen in Verbindung mit "do as server" zu treffen. 😉

      Man kann leider oft nur sagen: Grundsätzlich müsste es so und so funktionieren, aber ...
       

      • Dirk_Pulver
      • vor 4 Monaten
      • Gemeldet - anzeigen

      Ja - ich wollte da niemanden angreifen sondern diese "aber..." ist eben immer latent vorhanden, was es manchmal nicht so einfach macht. Man zieht sich dann auf die Varianten zurück, mit denen man zuverlässig Erfolg hatte. So bin ich z.B. bei jeder nachträglichen Umstellung wo man [do as server] einbaut immer sehr vorsichtig, ob das Gesamtscript damit noch zuverlässig läuft. Und oft tut es das eben nicht mehr - selbst wenn man keine Variablen von außen mitnimmt. Also dieses "So müsste es eigentlich funktionieren" kenne ich sehr gut. Ich habe diesbezüglich schon Pferde kotzen sehen - wie man so schön sagt.
      Und so ist es mit dem - für mich neuen - Hinweis, dass man [do as transaction] ja so einbauen kann, dass man einen  Rückgabewert daraus erhält und somit aber eine "slow-select" abfrage beschleunigen könnte. Das scheint tatsächlich zu klappen, aber eben bei mir nur da, wo ich in der Abfrage keinen Bezug auf den aktuellen Record nehmen muss. Also ist das ganze doch meist wieder sehr eingeschränkt verwendbar.
      Aber vielen Dank für die Mühe das ganze so zu testen.

    • mirko3
    • vor 4 Monaten
    • Gemeldet - anzeigen

    Nach meinen eigenen Tests habe ich es mal graphisch dargestellt. Das umgebende Script hat keinen Lese- oder Schreibzugriff auf do as...end. Jedoch hat do as...end lesenden Zugriff auf das restliche Script. In einer Funktion besteht auch schreibender Zugriff auf das restliche Script. Vielleicht kann man mit dieser Struktur das gesamte Script besser planen. Mirko

      • Dirk_Pulver
      • vor 4 Monaten
      • Gemeldet - anzeigen

      Ok, vielen Dank für die Mühe. In der Praxis ist es so dass man ja mit den do..as Schleifen die Performance optimieren möchte. Wenn man ein Script ganz damit kapseln kann, ist der Optimalfall. Das geht aber nicht immer. In komplexen Scripten, in denen man Teile kapseln möchte ist es meist so, dass zuvor Variablen bestehen, die teilw. im gekapselten Bereich verändert werden müssten um dann danach weiterverarbeitet zu werden. Das geht - wie wir sehen - nicht. Es wäre schön wenn man z.B. mit set global XY Variablen global verfügbar machen könnte (Lesen+Schreiben) die dann auch durch diese gekapselten Bereiche vollständig verwendet werden könnten - das wäre mal ein gutes Feature. Aber so wie jetzt sind diese do...as Konstrukte nur sehr begrenzt einsetzbar wenn man nicht unzählige Hilfsfelder anlegt die man Anstatt von Variablen verwendet werden. Sehr schade.