entitySelection.orderByFormula und Parameter

Hallo zusammen,

ich habe es erfolgreich geschafft den Befehl entitySelection.orderByFormula( ) zur Sortierung von Listboxen mit Entities einzusetzen. Auch die Übergabe von String- und Numerischen Parametern klappt wunderbar. Woran ich jedoch scheitere, ist die Übergabe eine EntitySelection einer Tabelle, die nicht direkt was mit der Listbox zu tun hat, aber zur Sortierung benötigt wird.
Was muss ich dabei beachten, bzw. ist das überhaupt unterstützt?

Systemumgebung: V18 Client/Server auf Mac

Vielen Dank
Jann Wegner

Sollte eigentlich gehen. Jedenfalls liefert das folgende Beispiel keinen Fehler:

<code 4D>
C_OBJECT($formula;$params;$companies)

$params:=New object() //Objekt settings
$params.args:=New object(“personen”;ds.Persons.all())

$formula:=Formula($1.personen.query(“Company_ID == :1”;This.ID).length)

$companies:=ds.Companies.all().orderByFormula($formula;dk ascending;$params)

</code 4D>

Stimmt - in dieser Form geht es.

Ich kann allerdings die Formel nicht in einen Einzeiler packen. Deshalb benutze ich eine Prozdur, die in “Formula” aufgerufen wird. Und da muss die EntitySelection mit hinein:

C_OBJECT($formula;$params;$companies)
$params:=New object() //Objekt settings
$params.args:=New object(“personen”;ds.Persons.all())
$formula:=Formula(procSortieren($1))
$companies:=ds.Companies.all().orderByFormula($formula;dk ascending;$params)

Mit (vereinfachter) procSortieren:
C_OBJECT($1;$SortArgs)
$SortArgs:=$1
$personen:=$SortArgs.personen
$0:=$personen.query(“Company_ID == :1”;This.ID).length)

Wenn ich in procSortieren Typ von $personen abfrage (“type($personen)”) bekommen ich “is text” zurück. Und $personen enthält nicht die EntitySelection sondern lediglich den Text “[object EntityCollection]”
Versuche ich in procSortieren auch $personen mit C_OBJECT zu typisieren, erhalte ich auch eine Fehlermeldung - da ja offensichtlich keine EntitySelection sonder lediglich ein Text übergeben wird :frowning:

: Jann WEGNER

$0:=$personen.query(“Company_ID == :1”;This.ID).length)

das liefert eine Entity Selection zurück.

Dokumentation:
https://doc.4d.com/4Dv18/4D/18/entitySelectionorderByFormula.305-4505923.de.html

Der Parameter formula wird für jede Entity der Entity Selection ausgeführt, das Ergebnis definiert die Position der Entity in der zurückgegebenen Entity Selection. Es muss ein sortierbarer Typ sein (boolean, Datum, Zahl, Text, Zeit, Null).

Ihre Zeile enthält ein ) zuviel, fehlt hier etwas?

Wenn Sie die länge zurückgeben wollen (wieviel gefunden), dann müssen Sie $0 als Longint deklarieren.
Und prüfen das auch wirklich eine Zahl kommt - nicht eine EntitySelection wie bei Ihnen (text “[object EntityCollection]”)

Danke für die Antwort
Die Klammer am Ende ist zuviel.

Mein Problem ist schon vor dem Berechnen des Rückgabewertes (der Anzahl). In der Prozedur procSortieren kommt eben nicht meine EntitySelection personen an, die in den args stecken sollte, sondern nur der erwähnte Text. Deshalb klappt es mit dem Längenberechnen nicht.

sorry, ohne ausführbaren Code basierend auf vereinfachten Beispielen kommen wir nicht wirklich weiter.

Ich könnte jetzt weiter raten:

Mit (vereinfachter) procSortieren:
C_OBJECT($1;$SortArgs)
$SortArgs:=$1
$personen:=$SortArgs.personen
$0:=$personen.query(“Company_ID == :1”;This.ID).length)

Das ist einmal zuviel.

Richtig wäre:
Mit (vereinfachter) procSortieren:
C_OBJECT($1;$SortArgs)
$SortArgs:=$1
$personen:=$SortArgs
$0:=$personen.query(“Company_ID == :1”;This.ID).length)

Fangen Sie doch bitte nochmal bei Ihrem funktionierenden Einzeiler an.

also beim Beispiel von Herrn Sakowski. Das ging bei Ihnen, richtig?
$formula:=Formula($1.personen.query(“Company_ID == :1”;This.ID).length)

Die ersetzen Sie jetzt mit:
$formula:=Formula(meineSuchmethode)

In Methode
meine Suchmethode kommt:

$0:=$1.personen.query(“Company_ID == :1”;This.ID).length

Das sollte weiter gehen. Richtig?
Dann bitte Variable für Variable mit Zwischenvariablen ersetzen. Immer nur eine auf einmal.
Und - klappt es?

Habe es jetzt nochmal ganz im kleinen versucht, und sehe, dass ich an der ganz falschen Stelle suche.
Im Einzelplatzbetrieb funktioniert es wunderbar!

Bei Client/Server erhalte ich folgende Fehlermeldung:

Fehler bei Ausführung der Methode “[Datensatz].DatenZeigen.o_ListBox” in Zeile 44
Selection cannot be sorted in table Datensatz of database ZS.dbase

1214 Selection cannot be sorted in table Datensatz of database ZS.dbase
1195 Cannot complete sequential sort
100 Speicherzuordnung fehlgeschlagen

Server ist ein MacPro mit 32 GB RAM mit macOS 10.13.6
Datenbankgröße knapp 2 GB
Bei Datenbankeigenschaften/Kompatibilität ist nichts eingetragen
Speicherverwaltung steht auf “Cache automatisch anpassen” mit max 4 GB
Überprüfung/Reparatur bringt keine Fehler
Fehlermeldung kommt auch nach Neustart mit 4D als einzige Anwendung, interpretiert wie kompiliert

: Jann WEGNER

100 Speicherzuordnung fehlgeschlagen

Testen Sie bitte zuerst einmal mit einer neu angelegten Struktur und Testdaten ob es da auch auftritt. Wenn ja, könnte es mit 10.13 zusammenhängen (wir testen derzeit natürlich verstärkt 10.15 und weiterhin 10.14, aber 10.13 läuft nur auf auf einzelnen Testrechnern, nicht mehr produktiv).

Ansonsten prüfen Sie bitte ob der Fehler in Ihrer Struktur auch auftritt, wenn Sie die On Server Startup und On Startup abschalten (so können keine Einstellungen verändert werden, wir brauchen diese als jetzt nicht zu prüfen) und legen eine Testmethode an, die Sie direkt aus dem Design Mode aufrufen.

Wenn das dann geht, nehme ich an das Sie Ihren Test in einem selbst gestarteten Prozess durchführen und dieser Prozess nicht genügend Stapelspeicher hat. Setzen Sie diesen auf 0 (=Automatik).

Das ist jetzt nur geraden. Kann richtig liegen, kann falsch liegen.
Wenn falsch fehlen mir Informationen. Bitte legen Sie einen TAOW Fall an, am besten mit dem oben angesprochenen Beispiel.

Hallo Herr Maul,

habe eine jungfräuliche Datendatei mit einer handvoll Datensätzen befüllt - Problem besteht bei Client/Server nach wie vor. Struktur ist angeblich fehlerfrei.
Habe wie empfohlen einen TAOW-Fall angelegt

Das hier ist Ihr Problem:

<code 4D>
es_Items:=ds.Items.query(“Projekt_PKID = :1”;<>vt_AktProjektPKID)
$vo_SortArgs:=New object()
$vo_SortArgs.args:=New object(“AlleItems”;es_Items)
MESSAGE(“Es wird nach Fehlstellen Merkmal 1 sortiert …”)
$vo_SortierFormel:=Formula($1.AlleItems.query(“DS_PKID = :1 & M1 = :2”;This.PKID;0).length)
es_DS:=es_DS.orderByFormula($vo_SortierFormel;$vo_SortArgs)
</code 4D>

Sie erzeugen mit es_Items eine ORDA selection.
Diese packen Sie dann in ein Object $vo_SortArgs.args
Und das versuchen Sie dann bei an orderByFormula zu übergeben.

Nur ist das ein Client-Objekt das auf dem Server nicht existiert - die Sortierung wird aber auf dem Server ausgeführt, nicht auf dem Client.

Wenn ich den Code richtig verstehe, machen Sie damit eine Art Suche in Auswahl.

Den Schritt müssen Sie weglassen, also in der Formel stattdessen
ds.Items.query(“Projekt_PKID =:1 and DS_PKID = :2 & M1 = :3”;<>vt_AktProjektPKID;This.PKID;0).length
verwenden

Danke für die flotte Fehleranalyse.

Es ist in der Tat eine Art “Suche in der Auswahl”.

Ihre Syntax führt auch zum erwünschten Ergebnis. Nur: Dabei wird die Suche nach Items.Projekt_PKID für jeden Datensatz meiner Listbox (ca. 10.000) durchgeführt. Und das führt bei der Anzahl an Datensätzen in der Tabelle Items (> 7 Mio., Tendenz steigend) zu einer deutlich spürbaren Laufzeitverlängerung. Konkret: Einzelplatz 1 Sekunde gegen 65 Sekunden. Die Vorauswahl reduziert die Tabelle Items auf ca. 500.000 Datensätze.

Gibt es eine Alternative für Client/Server?

probieren Sie doch bitte mal ein zusammengesetztes Index aus. Entweder über zwei Felder oder gleich über alle 3, wenn das öfters benötigt wird.
Das könnte das einfachste ohne Struktur/Codeänderung sein…

Bei 10.000 in der Listbox sind auch lokale Sortierungen (über Join) für den Endanwender zu langsam.