An dieser Stelle sind Unterschiede im Ergebnis von Formeln bei der Verwendung in Ansichten bzw. in Abhängigkeit des Datenbankservers sowie allgemeine Hinweise zur Verwendung von Formeln aufgeführt.

Umgang mit nicht existierenden Objekten

Wird auf ein nicht existierendes Objekt zugegriffen, wird in Ansichten Null zurückgegeben und damit der komplette Ausdruck Null.

Dieses Beispiel, um „EntityTitle Firma / EntityTitle Kontakt” auszugeben:

BAGetPrimarySource('<OrmCRMContact>', 'RelatedCompany', ?, ?, [EntityTitle]) + ' / ' + [EntityTitle]

gibt außerhalb von Ansichten bei einer nicht vorhandenen Firma „ / Kontaktname" aus, in Ansichten Null.

Die Lösung für Ansichten muß besser abgesichert werden, um dieses Verhalten zu vermeiden:

IsNull(BAGetPrimarySource('<OrmCRMContact>', 'RelatedCompany', ?, ?, [EntityTitle]), 'Keine Firma') + ' / ' + [EntityTitle]

Performance-Optimierung von Formeln mit vielen Datenbankabfragen

Formeln in einer Ansicht werden in genau eine Datenbankabfrage übersetzt und sind damit sehr performant. Werden Formeln außerhalb von Ansichten verwendet, können sie pro Formel zu mehreren Datenbankanfragen führen. Diese gilt es allerdings aus Performancegründen zu vermeiden.

Beispiel 1:
Werden in einer Maske zehn Felder auf Basis von Informationen aus einem über Relation zu ermittelnden Datensatz ausgeblendet, führt dies zu mindestens zehn Datenbankabfragen bei jedem Öffnen der Maske. Performanter wäre, die Felder in einer Gruppe zu organisieren und die Gruppe komplett auszublenden.

Beispiel 2:
Auch die Formel aus dem letzten Kapitel:

Iif(IsNull(BAGetPrimarySource('<OrmCRMContact>', 'RelatedCompany', ?, ?)), 'Keine Firma', BAGetPrimarySource('<OrmCRMContact>', 'RelatedCompany', ?, ?, [EntityTitle])) + ' / ' + [EntityTitle]

lässt sich für die Verwendung außerhalb von Ansichten optimieren zu:

IsNull(BAGetPrimarySource('<OrmCRMContact>', 'RelatedCompany', ?, ?), 'Keine Firma') + ' / ' + [EntityTitle]

Unterschiedliche Datentypen zusammenfügen

In Ansichten führt [EntityTitle] + ' / ' + [Created] zu einem Fehler. Außerhalb von Ansichten funktioniert diese Formel. In Ansichten muß [EntityTitle] + ' / ' + ToStr([Created]) verwendet werde.

Unterschiede bei ToStr()

Grundsätzlich kann die Umwandlung von Datentypen in eine Zeichenkette mit ToStr sowohl zwischen Ansichten und anderen Stellen aber auch innerhalb von Ansichten für unterschiedliche Datenbankserver unterschiedliche Ergebnisse liefern.

ToStr() ist quasi eine Konvertierung eines bestimmten Wertes in eine Text-Repräsentation. Die Stelle, an der diese Konvertierung durchgeführt wird, ist ein Aspekt, der das Ergebnis bestimmt. Besonders deutlich kann dies bei der Umwandlung eines Datumswertes (aber auch Zahlen mit entsprechenden Trennzeichen) werden (die Umwandlungen in den Beispielen dienen nur zur Illustration).

Wird die Funktion beispielsweise in einem berechneten Feld in einer Maske verwendet, so wird das Datum anhand der Benutzersprache (Locale) umgewandelt, so dass sich bei einem Benutzer mit deutscher Spracheinstellung beispielsweise “21.07.2022” ergibt. Diese Möglichkeit existiert bei der Nutzung in einer Ansicht nicht, da die Konvertierung in dem Fall nicht von der Applikation selbst sondern vom Datenbanksystem vorgenommen wird, d.h. hier liegt die Konvertierung nicht in unserer Hand und wir können nicht garantieren, dass die Konvertierung zwischen unterschiedlichen Datenbanksystemen (auch Versionen des gleichen Datenbanksystems) immer das gleiche Ergebnis liefert.

Aktuell ist das Ergebnis von ToStr() eines Datumswerts auf MSSQL und PostgreSQL identisch, die Funktion liefert ein Datum im ISO-Format (bsp: “2022-07-21 11:59:59.303385”). Offenbar spielen hier Regionseinstellungen des jeweiligen Servers nicht in die Konvertierung hinein.
Allerdings ist ToStr() ja nicht auf Datumswerte beschränkt, man könnte es beispielsweise auch zusammen mit Guids verwenden “ToStr([Oid])” … HIER sind die Ausgaben der unterschiedlichen Datenbanksysteme tatsächlich unterschiedlich: Auf MSSQL entsteht eine Guid mit Großbuchstaben, bei PostgreSQL eine mit Kleinbuchstaben. Also gibt es spätestens hier einen Unterschied. Weitere, wie beispielsweise mögliche Formatierungen von Nummern habe ich nicht geprüft.

Abschließend kann man also feststellen:

  • Die Ergebnisse von ToStr() unterscheiden sich abhängig vom konvertierten Datentypen mit hoher Wahrscheinlichkeit bei dem Vergleich zwischen “Berechnete Spalte” in Ansichten und “Berechnetes Feld” in Masken oder anderen Berechnungen, die nicht auf einer Datenbankabfrage basieren.
  • Beim Vergleich “Berechnete Spalte” in Ansichten gegen unterschiedliche Versionen des gleichen Datenbanksystems sind Unterschiede eher unwahrscheinlich, können aber natürlich in zukünftigen Versionen nicht ausgeschlossen werden.
  • Beim Vergleich “Berechnete Spalte” in Ansichten gegen Datenbanksysteme unterschiedlicher Hersteller existieren nachweislich Unterschiede abhängig vom konvertieren Datentyp.