Records: GET SETFILTER FIND etc.

26. September 2009 16:33

Viele NAV-Programmier-Einsteiger scheitern an der Datensatzbeschaffung per C/AL.
Wer mit technisch-abstrakten Beschreibungen kein Problem hat, findet mitterweile online schöne Hilfeartikel zum Thema:
Essential C/AL Functions - lesen! :-)

Dieser Artikel dagegen ist für Programmierneulinge gedacht, die problemorientiert an die Sache gehen möchten.
Ich versuche zu beschreiben, wie die "Maschine" denkt und daher Eingaben von euch erwartet: anhand des Beispiels eines Tellerwäschers (ihr) und seinem Helfer (NAV):-)

Wer dagegen einen Überblick über die vorhandenen Recordfunktionen und deren Unterschiede zueinander haben möchte, dem empfehle ich den englischsprachigen Eintrag bei mibuso: How to work with record-variables (version 2)?



Ich gehe im Folgenden davon aus, dass ihr wisst, was Recordvariablen sind und wie ihr diese deklariert.

GET: Auf einen einzigen, ganz bestimmten Datensatz zugreifen
    Ihr seid Tellerwäscher und müsst einen bestimmten Teller vorspülen. Diesen soll euch euer - etwas empfindliche - Kollege reichen. Damit derjenige den einen Teller auf Anhieb findet und Verwechslungen ausgeschlossen sind, beschreibt ihr ihm den Teller eindeutig, z.B. "Den ovalen mit der gelben Farbe!"- und genauso arbeitet GET in Navision.
    Ihr verweist mit der Recordvariable zunächst auf den Gegenstand (Tabelle "Teller") und beschreibt ihn dann eindeutig (Form: oval, Farbe: gelb).
    Das, was in NAV einen Datensatz in einer Tabelle eindeutig beschreibt, ist der Primärschlüssel (auch Primary Key oder kurz PK genannt). Ein Primärschlüssel kann aus einem Feld bestehen oder wie hier eben aus mehreren Feldern (Form und Farbe).
    Gäbe es eine Tabelle Teller in NAV mit den Primärschlüsselfeldern Form und Farbe, dann hätte euer Befehl in NAV in etwa so gelautet:
    Code:
    Teller.GET(oval, gelb); 
    Auf die Besonderheiten der Notation von sog. Optionsfeldern gehe ich an dieser Stelle nicht näher ein.

    Vorsicht Anfängerfalle!
    • Hierbei ist die Reihenfolge der einzelnen Felder innerhalb der Klammern wichtig - sie muss der Reihenfolge der Primärschlüsselfelder (s.u.) entsprechen.
      Euer Helfer weiß nicht, dass gelb eine Farbe und oval eine Form ist. Damit er weiß, welchen Wert er welcher Eigenschaft zuordnen soll, braucht er einer vordefinierte Reihenfolge.

    • GET erwartet in den Klammern Werte für jedes Schlüsselfeld, jedoch keine namentliche Auflistung der Schlüsselfelder!
      Wenn ihr Quelltext der Form
      Code:
      SalesHeader.GET("Document Type", "No."); 
      seht, so wird der Inhalt der Felder "Document Type" und "No." einer anderen Tabelle (als der, die ihr gerade nach SalesHeader "holen" wollt) übergeben!
      Der nachfolgende Code führt das Gleiche aus:
      Code:
      MyOptionVar := Rec."Document Type";
      MyCodeVar := Rec."No.";
      SalesHeader.GET(MyOptionVar, MyCodeVar); 

    • Was macht RecordXY.GET; ohne Parameter?

Wo kann ich den Primärschlüssel einer Tabelle nachsehen?
    • Wenn es eure Entwicklerlizenz erlaubt, sucht die Tabelle im Object Designer und klickt unten auf "Design". Hier seht ihr eine Auflistung aller Tabellenfelder.
      Wählt nun im Menü unter Ansicht -> Keys.
      Hier stehen nun ein oder mehrere Datensätze. Nur der oberste ist euer gesuchte Primärschlüssel.

      Beispiel:
      Stellt euch im Object Designer auf Tabelle 37 (Sales Line) und ruft deren Schlüssel auf.
      In der obersten Zeile steht:
      Code:
      Document Type,Document No.,Line No

      Es handelt sich hier also um einen Primärschüssel aus drei Feldern.


    • Reicht eure Lizenz nicht aus, dann öffnet in der Anwendung eine Form, die eure Tabelle anzeigt und klickt Ansicht -> Sortierung. Auch hier ist der oberste Eintrag der Primärschlüssel. Stellt NAV auf Englisch um, wenn ihr die englische Bezeichnung der Felder sehen wollt.

    Möchtet ihr ein GET auf die Tabelle Sales Line anwenden (konkret auf die erste Zeile (10000) des Auftrags 1014), erwartet NAV laut Primärschlüssel folgenden Aufbau:
    Code:
    SalesLine.GET(Auftrag, '1014', 10000);   // Achtung, syntaktisch noch nicht richtig    

    Damit der Compiler den Optionswert "Auftrag" versteht, müssen wir es jetzt nur noch etwas anders schreiben:
    Code:
    SalesLine.GET(SalesLine."Document Type"::Order, '1014', 10000); 

    Hättet ihr eurem Helfer gesagt: "Bring mir den dreieckigen Teller in Neongrün", hätte der wohl bitterlich geweint, weil er ihn nicht finden kann.
    NAV hätte euch dagegen einen Laufzeitfehler ausgegeben.

    :greenarrow: Nur wenn
    • ihr einen einzigen Datensatz sucht und
    • ihn eindeutig durch seine Primärschlüsselfelder beschreiben könnt,
    könnt ihr GET verwenden.
SETFILTER, FIND
    Ihr steht an der Spüle und möchtet, dass jemand (NAV) euch nacheinander alle ovalen Teller (Farbe ist also egal) reicht, damit ihr sie spülen könnt. Wie würdet ihr diese "Spülschleife" in NAV abbilden?
    Code:
    Teller.SETFILTER(Form, oval); // 1)
    IF Teller.FIND('-') THEN // 2)
      REPEAT
         
    // spüle Teller
      UNTIL Teller.NEXT = 0; // 3)     
    1. Hier sagt ihr eurem Helfer, wonach er die Teller auswählen soll.
      SETFILTER: zuerst kommt das Feld, auf das ihr filtern möchtet, danach der Wert, auf den ihr filtern möchtet.
      Wenn ihr euch das mit (...Form, oval) zu abstrakt vorkommt, denkt euch statt des Kommas einen Doppelpunkt, also (...Form: oval!)
    2. Erst mit FIND(...) läuft euer Helfer los und greift nach dem ersten Teller. In NAV heißt das: Erst jetzt wird eine Abfrage an die Datenbank geschickt (wobei der zuvor gesetzte Filter mit abgegeben wird).
      FIND('-') heißt, er soll nach dem ersten Teller greifen, den er findet.
      FIND('+') heißt, er soll nach dem letzten Teller greifen, den er findet.
      Euer Helfer würde weinen, würde er jetzt nicht mindestens einen Teller finden, auf den diese Beschreibung zutrifft! In NAV hätte dies bedeutet: Laufzeitfehler.
      Daher sagt ihr ihm: "Wenn du nichts findest, ist es trotzdem OK."
      NAV müsst ihr sagen: IF FIND THEN ....
    3. NEXT (ohne Parameter): Euer Helfer greift nach dem nächsten Teller. Ist keiner mehr da, ergibt das 0 -> Schleife zu Ende.
    Vorsicht Anfängerfalle!
    SETFILTER setzt noch keine Abfrage an die Datenbank ab. Diese wird erst mit FIND durchgeführt.

    FIND(...) wird verwendet, wenn
    • ihr mindestens einen Datensatz sucht (meistens jedoch mehrere),
    • den/welche ihr nicht durch seine Primärschlüsselfelder beschreiben könnt.

Nun gibt es noch SETCURRENTKEY, SETRANGE, FINDSET, FINDFIRST, ISEMPTY usw. - aber für den Anfang soll das reichen. :idea:
Ansonsten findet ihr hier einen schönen Blogartikel zu ISEMPTY, FINDFIRST, FINDLAST, FINDSET: Navision Performance-Optimierung auf dem SQL-Server

Was passiert bei Record.GET; (also ohne Parameter)?

18. März 2010 10:49

Jörg Nissen hat geschrieben:habe mal in einem quelltext ein
Code:
record.get;
sprich get ohne parmeter gesehen.
Was passiert hier ?

McClane hat geschrieben:Kenn ich nur von Einrichtungstabellen, also zB Company Information. Das zieht den Datensatz mit leerem PK.

Korrekt. Deutlicher wird es, wenn man es so schreibt (mach ich selber so nicht, der Standard auch nicht, ist aber im Grunde genauso richtig):
Code:
Einrichtungstabelle.GET('');


Hintergrund: Alle Einrichtungstabellen haben einen Primärschlüssel, der aus einem einzigen Feld, nämlich "Primary Key" besteht. Wenn ein Datensatz erzeugt wird, so immer mit "Primary Key" = leer.
Vorteile:
1. GET liefert automatisch den Datensatz; ich muss nicht mit FIND(FIRST) arbeiten, da ich den PK-Inhalt (= leer) bereits kenne.
2. In jeder Einrichtungstabelle kann (im Standard, durch den Anwender) max. ein Datensatz erzeugt werden

Re: Records: GET SETFILTER FIND etc.

18. März 2010 11:04

Natalie hat geschrieben:2. In jeder Einrichtungstabelle kann max. ein Datensatz erzeugt werden

Wer unbedingt möchte, kann auch mehrere da rein schreiben. Wär halt nur sinnlos, da immer auf den DS mit leerem PK zugegriffen wird.

Re: Records: GET SETFILTER FIND etc.

28. März 2010 01:43

McClane hat geschrieben:
Natalie hat geschrieben:2. In jeder Einrichtungstabelle kann max. ein Datensatz erzeugt werden

Wer unbedingt möchte, kann auch mehrere da rein schreiben. Wär halt nur sinnlos, da immer auf den DS mit leerem PK zugegriffen wird.

In Projekten sind mir auch schon Einrichtungstabellen mit mehr als einem Datensatz begegnet, auf die anderen wurde dann aus Individualprogrammierungen zugegriffen. Nicht unbedingt empfehlenswert, wenn der Platz ( 4000 Byte) nicht reicht sollten besser neue Tabellen erstellt werden. Auf gar keinen Fall darf dabei natürlich der leere PK im Standarddatensatz auch einen Wert erhalten, dann geht sofort gar nichts mehr :!: ( auch ein Fall aus der Praxis :wink: )

Re: Records: GET SETFILTER FIND etc.

26. Juni 2018 17:55

Bei der Erklärung, muss ich voraussetzen, dass eine Form (oval) und Farbe (gelb) in der Tabelle existiert?

Ich möchte realisieren, dass die Daten aus dem ausgewählten Objekt (Zeile) ausgelesen werden.... dafür ist der befehl nicht geeignet oder ?

MFG

Re: Records: GET SETFILTER FIND etc.

27. Juni 2018 08:17

derPat18 hat geschrieben:Bei der Erklärung, muss ich voraussetzen, dass eine Form (oval) und Farbe (gelb) in der Tabelle existiert?

Ja. Dieses Konzept des Vorhandenseins und Reihenfolge der eindeutigen Merkmale nennt sich in NAV "Primärschlüssel" :-)

Ich möchte realisieren, dass die Daten aus dem ausgewählten Objekt (Zeile) ausgelesen werden.... dafür ist der befehl nicht geeignet oder ?

Mir ist nicht ganz klar, was du willst.
Nur einen, ganz bestimmten Datensatz holen? --> GET
Alle Datensätze einer Tabelle: IF FINDSET THEN REPEAT UNTIL ...
Bestimmte Datensätze einer Tabelle: SETRANGE oder SETFILTER + IF FINDSET THEN REPEAT UNTIL ...
Je Datensatz (egal wie der geholt worden ist) kannst du alle Felder auslesen oder Feldwerte ändern.

Re: Records: GET SETFILTER FIND etc.

27. Juni 2018 08:23

derPat18 hat geschrieben:Bei der Erklärung, muss ich voraussetzen, dass eine Form (oval) und Farbe (gelb) in der Tabelle existiert?

Wenn du Teller.GET('oval','gelb'); schreibst, und kein passender Datensatz gefunden wird (weil er nicht existiert), dann bekommst du eine Fehlermeldung und dein Programmcode bricht ab (Rollback).
Schreibst du jedoch
Code:
IF Teller.GET('oval','gelb') THEN BEGIN
  
// Teller gefunden
END ELSE BEGIN
  
// Teller NICHT gefunden
END;

dann kannst du auf das Ergebnis reagieren.

Re: Records: GET SETFILTER FIND etc.

27. Juni 2018 20:18

Ich möchte realisieren, dass die Daten aus dem ausgewählten Objekt (Zeile) ausgelesen werden.... dafür ist der befehl nicht geeignet oder ?

Mir ist nicht ganz klar, was du willst.
Nur einen, ganz bestimmten Datensatz holen? --> GET
Alle Datensätze einer Tabelle: IF FINDSET THEN REPEAT UNTIL ...
Bestimmte Datensätze einer Tabelle: SETRANGE oder SETFILTER + IF FINDSET THEN REPEAT UNTIL ...
Je Datensatz (egal wie der geholt worden ist) kannst du alle Felder auslesen oder Feldwerte ändern.[/quote]

Also: User hat eine Page vor sich (ListPagePart) .. diese enthält zurZeit nur 1 Datensatz (warum und weshalb, ist mir noch unklar, da Ursprungstabelle/Page viel mehr Datensätze hat).
Jetzt makiert der User eben (z.b.) Diesen Datensatz (wenn 2. dann will ich ja nur Daten aus den makierten Datensatz haben)
Dann klickt er auf eine PageAction und eine neue Page öffnet sich , und in dieser Page wird die "Menge" aus der ursprünglichen ListPartPage übertragen - ist da get sinnvoll?



Und zum Allgemeinen Verständnis, mir will sich das noch nicht so recht erschließen (vielleicht muss ich mir das bildlich vorstellen, wie der Rechner "Denkt")
Ich habe eine Tabelle Teller (Anhang). Diese hat 3 Datensätze.

Der PK besteht aus 2 Feldern (anderes Wort für spalten?). Form und Farbe

Wenn ich nun mit
Code:
Record.GET(oval, gelb); //oval ist der 1. PK - Form ; gelb ist der 2. PK - Farbe?


bekomme ich doch theoretisch 3 Datensätze?
Also wenn es 3 Teller (mit unterschiedlichen Nummern und Typen) gibt aber eben immer oval und gelb

Sorry wenn ich so blöde Newbie Fragen stelle :D

MFG
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Re: Records: GET SETFILTER FIND etc.

28. Juni 2018 08:56

Hallo Patrick,
Primärschlüssel bedeutet, dass der Datensatz eindeutig identifizierbar ist.
Wenn du drei Teller hast, die gelb und oval sind, sind sie darüber nicht eindeutig identifizierbar. Also kann das nicht der Primärschlüssel sein.
In deinem Beispiel sind die Teller also über die Tellernummer eindeutig identifizierbar.
Sprich, du müsstest den GET Befehl mit der entsprechenden Nummer ausführen.

Re: Records: GET SETFILTER FIND etc.

28. Juni 2018 09:13

ach jetzt wird mir das klar!

damit er noch zusätzlich eindeutig ist, muss ich den PK noch die Teller_Nummer zuordnen?

Also

Code:
Record.GET(112, oval, gelb); //112 ist der 1. PK - Teller_Nummer (der ja dann natürlich eindeutig ist) ;oval ist der 2. PK - Form ; gelb ist der 3. PK - Farbe


Ist das richtig?

Re: Records: GET SETFILTER FIND etc.

28. Juni 2018 09:18

Hi Patrick,
nicht ganz - der Primärschlüssel wird bei dir vermutlich nur die Nummer sein.
Ansonsten hättest du auch folgende Konstellationen die eindeutig wären (aber nicht wirklich sinnvoll)

  • 1, oval, gelb
  • 1, oval, grün
  • 1, eckig, gelb
  • 1, eckig, grün
  • 2, oval, gelb
  • und so weiter

Form und Farbe sind also keine Schlüsselwerte, sondern einfache Eigenschaften.

Um alle gelben und ovalen Teller zu finden, würdest du mit SETRANGE arbeiten können, und dann in einer Schleife alle gefundenen Datensätze durchlaufen.

Re: Records: GET SETFILTER FIND etc.

28. Juni 2018 09:53

Danis hat geschrieben:Hi Patrick,
nicht ganz - der Primärschlüssel wird bei dir vermutlich nur die Nummer sein.
Ansonsten hättest du auch folgende Konstellationen die eindeutig wären (aber nicht wirklich sinnvoll)

  • 1, oval, gelb
  • 1, oval, grün
  • 1, eckig, gelb
  • 1, eckig, grün
  • 2, oval, gelb
  • und so weiter

Form und Farbe sind also keine Schlüsselwerte, sondern einfache Eigenschaften.


also

Code:
Record.GET (112, gelb, oval); //das würde also entweder alle Datensätze mit der Nummer 112 oder alle Datensätze mit der Form Oval oder alle Datensätze mit der Farbe gelb aussuchen?


Wenn ich jetzt nur die Nummer als PK (was bei fortlaufender Nummer der Datensätze sinn ergibt) arbeiten würde, wäre das ja eindeutig

Code:
Record.GET (112);

oder?

Danis hat geschrieben:Um alle gelben und ovalen Teller zu finden, würdest du mit SETRANGE arbeiten können, und dann in einer Schleife alle gefundenen Datensätze durchlaufen.


das Bedeutet, ich müsste den Code anders schreiben zum eindeutig identifizieren (wenn ich nach allen 3en Suche Nummer, Form, Farbe):

Code:
Record.SETRANGE (112, oval, gelb);  //das würde also DEN 3. Datensatz (den wir haben wollen) mit der Nummer 112 UND der Form Oval UND der Farbe gelb aussuchen?


das Ganze in eine Repeat until (Solange bis) Schleife packen?


Also kann GET nur mit 1 PK arbeiten (der eindeutig ist) und SETRANGE eben mit mehreren PKs für 1 Datensatz?

Re: Records: GET SETFILTER FIND etc.

29. Juni 2018 09:58

Jeder Datensatz hat genau einen Primärschlüssel. Dieser wiederum kann aus einem oder aber auch mehreren Feldern bestehen.

Record.GET (112, gelb, oval); //das würde also entweder alle Datensätze mit der Nummer 112 oder alle Datensätze mit der Form Oval oder alle Datensätze mit der Farbe gelb aussuchen?

Nein, der Befehl würde nur funktionieren, wenn alles 3 Felder zusammen den Primärschlüssel bilden und dir dann genau den einen Datensatz mit der Nr. 112, der Farbe "gelb" und der Form "oval" liefern.

Record.SETRANGE (112, oval, gelb); //das würde also DEN 3. Datensatz (den wir haben wollen) mit der Nummer 112 UND der Form Oval UND der Farbe gelb aussuchen?

Wenn die Nr. der Primärschlüssel ist und du diese kennst, ergibt ein SETRANGE hier wenig Sinn. Dann kannst du den Datensatz mit Record.GET(112) lesen.

Willst du hingegen herausfinden welche Teller alle gelb und oval sind, musst du wie folgt vorgehen.

Code:
Record.SETRANGE(Form,'oval');
Record.SETRANGE(Farbe,'gelb');
IF Record.FINDSET THEN
  REPEAT
     MESSAGE('%1',Record."Nr.");
  UNTIL Record.NEXT = 0;

Re: Records: GET SETFILTER FIND etc.

29. Juni 2018 12:33

AVS hat geschrieben:Jeder Datensatz hat genau einen Primärschlüssel. Dieser wiederum kann aus einem oder aber auch mehreren Feldern bestehen.


Gibt es net nur 1 PK (der 1. bei Ansicht - Keys) in der Tabelle und der Rest sind Secondary Keys?
( Zitat von Natalie - ganz oben:
[*]Reicht eure Lizenz nicht aus, dann öffnet in der Anwendung eine Form, die eure Tabelle anzeigt und klickt Ansicht -> Sortierung. Auch hier ist der oberste Eintrag der Primärschlüssel. Stellt NAV auf Englisch um, wenn ihr die englische Bezeichnung der Felder sehen wollt.
)




Code:
Record.GET (112, gelb, oval); //das würde also entweder alle Datensätze mit der Nummer 112 oder alle Datensätze mit der Form Oval oder alle Datensätze mit der Farbe gelb aussuchen?


Nein, der Befehl würde nur funktionieren, wenn alles 3 Felder zusammen den Primärschlüssel bilden und dir dann genau den einen Datensatz mit der Nr. 112, der Farbe "gelb" und der Form "oval" liefern.


super danke, jetzt habe ich es kapiert, GET sucht nur 1 bestimmten Datensatz ... in dem Beispiel von mir muss also der PK zusammengesetzt sein =)

Code:
Record.SETRANGE (112, oval, gelb);  //das würde also DEN 3. Datensatz (den wir haben wollen) mit der Nummer 112 UND der Form Oval UND der Farbe gelb aussuchen?


Wenn die Nr. der Primärschlüssel ist und du diese kennst, ergibt ein SETRANGE hier wenig Sinn. Dann kannst du den Datensatz mit Record.GET(112) lesen.

Willst du hingegen herausfinden welche Teller alle gelb und oval sind, musst du wie folgt vorgehen.

Code:
Record.SETRANGE(Form,'oval');
Record.SETRANGE(Farbe,'gelb');
IF Record.FINDSET THEN
  REPEAT
     MESSAGE('%1',Record."Nr.");
  UNTIL Record.NEXT = 0;


Also ist SETRANGE nur gut wenn man mehrere Datenssätze suchen will (gegenteil von GET)?
Muss dann net irgendwie im Code spezifiziert werden, dass EIN Gefundener Datensatz zur Ausgabe eine Variable bekommt z.b. "A" bekommt und eben der 2. gefundene Datensatz "B" bekommt usw.?


Wenn wir schon dabei sind, wie kann ich eigentlich diesen Gefundenen datensatz (z.b. jetzt mit GET) ausgegen in ein Feld (sagen wir, ich will nur ein bestimmtes Feld aus diesem gefundenen Datensatz)?

Re: Records: GET SETFILTER FIND etc.

29. Juni 2018 13:42

Vielleicht solltest du dir diese Videos mal anschauen.
https://www.youtube.com/watch?v=XNLOb3n ... K52KqqgNgz

Re: Records: GET SETFILTER FIND etc.

16. Januar 2019 15:26

hallo, nach fast 1 Jahr habe ich mich wieder den Thread mal durchgelesen :)
zwar ist mir im Gegensatz zu früher einiges klarer, jedenfalls kommt für mich noch nicht richtig die Erleuchtung was FIND macht

GET liefert ja einen spezifischen Datensatz anhand des PK

FIND Findet Daten/Datensatz und speichert sie erstmal in einer temporären Variable?

Und das mit SETFILTER wurder mir auch nicht ganz klar, wenn Sie/Ihr mal nochmal kurz darauf eingehen könntet ? :)

MFG

Re: Records: GET SETFILTER FIND etc.

16. Januar 2019 15:49

https://docs.microsoft.com/en-us/dynamics-nav/get--find--and-next-functions
Da solltest du eigentlich alles finden.

Setfilter setzt einen Filter auf ein Feld.
Und mit Find('-') holst du dir die (gefilterten) Datensätze und durchläufst sie mit Repeat > Next

Re: Records: GET SETFILTER FIND etc.

17. Januar 2019 09:34

derPat18 hat geschrieben:... was FIND macht

GET liefert ja einen spezifischen Datensatz anhand des PK

FIND Findet Daten/Datensatz und speichert sie erstmal in einer temporären Variable?

Und das mit SETFILTER wurder mir auch nicht ganz klar...


Ich empfehle http://www.navision24.de falls das noch niemand hier empfohlen hat.

Ansonsten ist es am Anfang etwas schwierig GET, SETRANGE, SETFILTER, FINDSET, FINDFIRST, REPEAT etc. zu verstehen, wenn man noch nie mit relationalen Datenbanken zu tun hatte, wie zB SQL-Server und man vielleicht noch nicht weiss, was primary key, foreign key, table relations, JOINs etc. sind.

GET ( ) ist anzuwenden, wenn du nur auf den primary key (ein einzigartiges Feld oder eine einzigartige Kombination aus Feldern) zeigen ("filtern") möchtest. Bei Debitor, Kreditor, Artikel ist das "No.", wohingegen bei SalesLine das 3 Felder sind.

Damit du dich absicherst, sollstest du immer GET in eine Bedingung einbetten: IF Tabelle.GET ( ) THEN tue irgendwas. Entspricht in den modernen Sprachen wie Java und C# dem try { } catch { } Konstrukt, wenn ich mich recht erinnere.


Bsp: angenommen dieses Forum wäre eine NAV Tabelle und seine Benutzer würden auch in einer NAV Tabelle verwaltet, dann könnte ich schreiben

Code:
IF MSDynamicsUser.GET('derPat18') THEN

Message ("das ist ein gültiger Zugriff auf primary key der Tabelle MSDynamicsUser");

ELSE

Message ("Zugriff ins Nirvana wurde durch IF THEN Konstrukt verhindert, User derPat18 existiert nicht")



SETRANGE ( ) ist anzuwenden, wenn auf foreign keys oder nur auf non_primary keys (Felder) per Vorfilterung zugreifen willst.

Bsp, wie man u.a. dich und andere User mit den 3 Merkmalswerten männlich, schwarze Haare und 18 jährig finden kann:

Code:
MSDynamicsUser.SETRANGE(Geschlecht,"männlich"); //erster Filter
MSDynamicsUser.SETRANGE(Haare,"schwarz"); //zweiter Filter
MSDynamicsUser.SETRANGE(Alter,"18"); //dritter Filter
MSDynamicsUser.SETCURRENTKEY( hier die gewünschte Sortierung gem. NAV eintragen, d.h. Feldreihenfolge );

//Achtung: wenn nach SETRANGE eine Schleife kommen sollen, dann NIE Tabelle.FINDFIRST nutzen, sondern Tabelle.FINDSET. Tabelle.FINDFIRST bzw. Tabelle.FINDLAST nur benutzen, wenn du ohne Schleife auf den vorgefilterten und vorsortierten Block an Datensätzen exakt auf den ersten oder letzten zugreifen willst:

IF MSDynamicsUser.FINDSET THEN

REPEAT

i := i + 1; //i wurde unter local variables als int Variable definiert

Message ('%1',"User namens :" '%2',  "gefunden", 'i', 'UserID'); //UserID ist primary Key von MSDynamicsUser, und %1, %2 bitte bei navision24 gucken, ob ich das korrekt gesetzt habe

UNTIL MSDynamicsUser.NEXT(+1) = 0  //das +1 wird weggelassen, da die default iteration in NAV von oben nach unten geht.



SETFILTER geht -soweit ich mich erinnere- über SETRANGE hinaus. Im SETFILTER kannst du < = > abfragen.

MSDynamicsUser.SETFILTER(Alter,'%1','%2','>','18') //das würde dich dann herausfiltern, da > 18 als Kriterium

IM SQL-Server geht das Ganze viel schneller:

Code:
SELECT UserID, UserName

FROM dbo.MSDynamicsDB.MSDynamicsUser

WHERE Geschlecht = 'männlich' AND Haare = 'schwarz' AND Alter = '18'  // weiss nimmer, ob ' ' oder " " oder gar keine, muss man ausprobieren



Deshalb empfehle ich, für "Management-Reports", die LESEND über zig Mio Datensätze gehen, nicht einen NAV Report zu stricken, sondern im SQL-Server eine Datenbasis zu erstellen (meinetwegen Nachtjob, Zwischentabellen oder gar DWH) und per Reporting Services die Darstellung zu ermöglichen. Denn im SQL-Server kannst du schneller per JOINs Datenmiteinander verknüpfen als mit SETRANGE, SETFILTER auf mehreren NAV-Tabellen in C/AL und dann IF THEN ELSE blah Verknüpfung der zig Tabellen und dann ausgabe per RTC-Report.

Unbedingt aber beachten, dass dieser lesende Zugriff, wenn zig Mio Bewegungsdaten auszulesen wären, immer dann erfolgt, wenn die User nicht an NAV arbeiten. Sonst kann bei suboptimaler Konfiguration des oder der ServiceTiers NAV in die Knie gehen.

EDIT: ich empfehle dir fürs grundlegende Verständnis, wie relationale Datenbanken funktionieren (ERP ist "nur" ein Frontend mit Business Logik, im Hintergrund werkelt immer ein RDBMS), die die Demoversion von SQL-Server 2017 zu holen. Läuft 180 Tage. Dann holst du dir die alte Northwind DB und danach Adventure Works. Und guckst im YouTube wie du sie einbindest. Dann gibt es im Internet Aufgaben mit Musterlösungen. Wenn du sie nicht findest, einfach mich per PM hier fragen.
Sobald du das abgearbeitet hast, kriegst du ein grundlegendes Gespür für Datenbanken, Tabellen, Zeiger (relations), Lesezugriff, Schreibzugriff, Verknüpfung (JOINs). Und danach das Ganze gedanklich mit C/AL umsetzen. Oder du hast von jmd eine Entwicklerlizenz (auch eine uralte, wo du das Windowsdatum umstellen musst) und installierst dir NAV mit SQL-Server mit Management Studio. Danach erzeugst du dir mit der Entwicklerlizenz im Objektdesigner mehrere 50000er Tabellen mit den gleichen Keys (Feldern) und Datentypen wie Northwind und AdventureWorks. Anschliessend kopierst du dir die Daten von den Northwind Tabellen in die neuen 50000er Tabellen und versuchst per C/AL die gleichen Ergebnisse zu produzieren wie mit TSQL.

Bevor ich auf irgendwelche Daten zugrife, male mich mir mehrere Kreise auf (VENN-Diagramm) und gucke, ob sich die gesuchten Daten in einem oder mehreren Kreisen befinden, ob sich die Kreise (nicht) überschneiden und erst dann baue ich mir gedanklich die JOINs auf. Danach der C/AL Code, wo SETRANGE, IF FINDSET THEN, REPEAT UNTIL stehen => ergibt sich automatisch, wenn man JOINs und VENN-Diagramm beherrscht.

Auch wichtig zu verstehen: wenn man auf einer Tabelle sortiert, filtert ausliest und in eine andere leere Tabelle schreiben will, dann ist die Filterung umgekehrt:
Auf die mit Datensätzen gefüllte Quelltabelle mit SETCURRENCTKEY, SETRANGE, IF FINDSET THEN, REPEAT UNTIL zugreifen und auslesen.
Aber auf die leere Tabelle mit IF NOT FINDSET THEN REPEAT ... INIT INSERT ... UNTIL wenn man das erste mal was befüllt.
Ich habe manchmal als Anfängerfehler gesehen, dass die Filterung auf der vollen Quelltabelle 1:1 kopiert wird auf die Filterung der leeren Tabelle und dann wundert man sich, warum die Schreibzugriff nicht klappt.

Die meisten erfahrenen C/AL Entwickler Ü40 haben damals vor 10-20 Jahren mit Borland Delphi, Access oder Visual Basic hantiert. Deshalb ist für sie vieles bekannt. Für einen absoluten Neuling, der in die prozedurale / objektbasierte (nicht objektorientierte) Entwicklung mit NAV einsteigt, ist es am Anfang schwierig.

EDIT 2: wenn du per SETRANGE oder SETFILTER auf Felder zugreifen musst, die FlowFields sind, dann immer zuerst:

CALCFIELDS(FlowFieldName); und dann
SETRANGE(FlowFieldName, Parameter) ... IF FINDSET THEN ... REPEAT UNTIL ...
Zuletzt geändert von ERP-Berater am 6. März 2019 10:16, insgesamt 1-mal geändert.

Re: Records: GET SETFILTER FIND etc.

17. Januar 2019 13:37

Danke für die ausführliche Antwort!
Ja zum glück bekomme ich in nächster Zeit von meinen Bildungsträger eine umfassende Schnell Schulung in Sachen Datenbanken,Programmierung,OOP ^^

Re: Records: GET SETFILTER FIND etc.

17. Januar 2019 14:28

Jetzt aber bitte Schluss mit Schulungen machen und ans Thema des Beitrags halten.