Daten zwischen Tabellen mit DataTransfer übertragen
Bei der Umgestaltung einer App ist es üblich, ein Feld von einer Tabelle in eine andere zu verschieben oder alle Daten von einer Tabelle in eine andere Tabelle zu kopieren. Mithilfe dieser Funktion kann der Entwickler die Daten aus dem alten Feld in das neue Feld oder die Daten aus der alten Tabelle in die neue Tabelle satzbasiert kopieren, ohne eine Schleife schreiben zu müssen. Auf dieser Art ist es möglich, Upgrade-Code deutlich schneller zu schreiben.
DataTransfer ist ein AL-Datentyp, der die Massenübertragung von Daten zwischen SQL-basierten Tabellen unterstützt. DataTransfer erzeugt SQL-Code, der mit Sätzen arbeitet, anstatt nach einem zeilenweisen Modell zu arbeiten, wie es die Datensatz-API tut. Dadurch wird die Leistung beim Verschieben von Daten während des Upgrades verbessert.
Im Vergleich wird durch den folgenden Code veranschaulicht, wie Zeilen mit der Datensatz-API kopiert werden:
al-languageCopy
local procedure CopyRows()
var
from: Record FromTable;
to: Record ToTable;
begin
if from.Find() then
repeat
to.SmallCodeField := from.SmallCodeField;
to.IntField := from.IntField;
to.id := from.id;
to.Insert();
until from.Next() = 0;
end;
Das Gleiche kann mit DataTransfer erreicht werden:
al-languageCopy
local procedure CopyRows()
var
dt: DataTransfer;
to: Record ToTable;
begin
dt.SetTables(Database::FromTable, Database::ToTable);
dt.AddFieldValue(2, to.FieldNo("SmallCodeField"));
dt.AddFieldValue(3, to.FieldNo("IntField"));
dt.AddFieldValue(1, to.FieldNo("id"));
dt.CopyRows();
end;
Das Objekt DataTransfer kann im Wesentlichen für zwei Vorgänge genutzt werden:
Kopieren Sie Daten aus einem oder mehreren Feldern einer Tabelle in Felder einer anderen Tabelle. Ein obsolet gemachtes Feld stellt ein typisches Szenario dar.
Kopieren Sie Daten aus ganzen Zeilen einer Tabelle in Zeilen einer anderen Tabelle. Eine obsolet gemachte Tabelle stellt ein typisches Szenario dar.
Das Objekt DataTransfer kann nur in Upgrade-Code verwendet werden. Wenn es außerhalb von Upgrade-Codeunits verwendet wird, löst es einen Laufzeitfehler aus.
Das Objekt DataTransfer kann nicht für folgende Tabellen verwendet werden:
Nicht-SQL-Tabellen
Systemtabellen
Virtuelle Tabellen
Geprüfte Tabellen als Ziel
Obsolete Tabellen als Ziel
DataTransfer verwendet ein Entwurfsmuster, das im Allgemeinen erfordert, dass Sie die folgenden Schritte ausführen:
Rufen Sie die SetTables auf, um die Quell- und Zieltabellen anzugeben.
Rufen Sie AddFieldValue auf, um die zu übertragenden Felder oder konstanten Werte anzugeben. Mit AddConstantValue können Sie jeweils einen konstanten Wert für Felder im Ziel festlegen.
Rufen Sie AddJoin aus, um die Beziehung zwischen den Quell- und Zieltabellen festzulegen. Diese Methode ist meistens erforderlich, um Felder zu kopieren.
Rufen Sie AddSourceFilter auf, um Einschränkungen für die zu übertragenden Daten hinzuzufügen.
Rufen Sie CopyFields oder CopyRows auf, um die Abfrage zum Übertragen von Daten aufzurufen.
DataTransfer wird in großen Mengen und nicht zeilenweise ausgeführt, aus diesem Grund werden zeilenbasierte Ereignisse oder Trigger nicht ausgeführt. Beim Aufrufen von CopyFields wird zum Beispiel keines der folgenden Ereignisse aufgerufen: OnBeforeModify, OnModify oder OnAfterModify. Oder es wird beim Aufruf von CopyRows keines der folgenden Ereignisse aufgerufen: OnBeforeInsert, OnInsert oder OnAfterInsert.
Felder kopieren
Durch Aufrufen von CopyFields auf dem Objekt DataTransfer werden ausgewählte Felder aus einer Tabelle (der Quelle) in eine andere Tabelle (die Ziel) kopiert. Es ist erforderlich, eine Join-Bedingung einzugeben, sofern Sie nicht mit derselben Quell- und Zieltabelle kopieren. Die Join-Bedingung gibt an, wie Zeilen der Quelltabelle mit Zeilen der Zieltabelle abgeglichen werden.
Ein Feld als veraltet einzurichten und die Daten in eine andere Tabelle zu verschieben, ist ein typisches Szenario. Nehmen wir zum Beispiel an, Sie haben zwei Tabellen, Quelle und Ziel, wie unten mit Beispieldaten veranschaulicht. Sie planen, das Feld S3 in der Tabelle Quelle als veraltet einzurichten. Sie möchten vorher jedoch einige Werte von S3 in das Feld D3 der Tabelle Ziel kopieren. Genauer möchten Sie das Feld S3 in Zeilen kopieren, in denen das Feld S2 A entspricht.
Der Code zum Ausführen dieses Vorgangs lautet folgendermaßen:
al-languageCopy
local procedure CopyFields()
var
dt: DataTransfer;
dest: Record Destination;
src: Record Source;
begin
dt.SetTables(Database::Source, Database::Destination);
dt.AddFieldValue(src.FieldNo("S3"), dest.FieldNo("D3"));
dt.AddSourceFilter(src.FieldNo("S2"), '=%1', 'A');
dt.AddJoin(src.FieldNo("PK"), dest.FieldNo("PK"));
dt.CopyFields();
end;
Das gleiche Szenario könnte auch für die Datensatz-API geschrieben sein mit einer Schleife über alle Zeilen in der Tabelle Quelle mit einem Filter auf dasFeld S2, dann wird für jede Abstimmung die Option Abrufen im Zieldatensatz aufgerufen, die Felder werden eingerichtet und Bearbeitenwird aufgerufen.
Die datensatzbasierte Lösung führt drei SQL-Operationen pro Zeile aus, während DataTransfer maximal zwei SQL-Abfragen insgesamt durchführt. Messungen für DataTransfer‑ und Aufzeichnungs-API-Lösungen haben eine ~200-fache Steigerung der Leistung für DataTransfer gezeigt. Die Gewinne sind sogar noch größer, wenn die Zieltabelle Änderungstrigger hat oder wenn die Umgebung über eine erhebliche Latenz zu SQL verfügt.
Die Join-Bedingung kann für beliebige Felder angegeben werden. Dadurch besteht die Möglichkeit, dass der Satz von Feldern keinen eindeutigen Satz von Zeilen für diesen Satz von Feldern erzeugt. Diese Situation führt dann zu einer n:n-Beziehung zwischen den Tabellen. Eine n:n-Beziehung erfordert, dass die Laufzeit weiß, welche Zeile auszuwählen ist. Im besten Fall werden diese zufällig ausgewählt. Die Upgrade-Laufzeit erkennt stattdessen diese Situation und zeigt einen Fehler an. Die folgende Tabelle zeigt ein Beispiel, bei dem das Verbinden der Felder S1 und S2 keinen eindeutigen Satz von Zeilen erzeugt, und daher zu einem Laufzeitfehler führen würde.
Durch Aufrufen von CopyRows für das DataTransfer-Objekt wird für jede übereinstimmende Zeile in der Quelltabelle eine Zeile in die Zieltabelle hinzugefügt. Felder in der eingefügten Zeile werden mit Werten ausgefüllt, die durch das Aufrufen von AddFieldValue oder AddConstantField angegeben werden. Felder, die nicht in AddFieldValue oder AddConstantField festgelegt wurden, werden nicht in diesem Feld InitValue oder dem Standardwert ausgefüllt.
Wenn der Code versucht, eine Zeile aus der Quelltabelle zu kopieren, die denselben Primärschlüssel wie eine vorhandene Zeile der Zieltabelle hat, wird ein Laufzeitfehler generiert.
Betrachten Sie erneut das Beispiel mit den Beispieltabellen Quelle und Ziel, um CopyRows besser zu verstehen.
In diesem Code-Beispiel kopieren Sie die Felder PK und S3 für alle Zeilen, in denen S2 A entspricht, und fügen Sie dann der Tabelle Ziel hinzu. Verwenden Sie die Methode AddConstantValue, um dem Feld D2 den Wert X in den eingefügten Zeilen zu geben.
al-languageCopy
local procedure CopyRows()
var
dt: DataTransfer;
src: Record Source;
dest: Record Destination;
begin
dt.SetTables(Database::Source, Database::Destination);
dt.AddFieldValue(src.FieldNo("PK"), dest.FieldNo("PK"));
dt.AddFieldValue(src.FieldNo("S3"), dest.FieldNo("D3"));
dt.AddConstantValue('X', dest.FieldNo("D2"));
dt.AddSourceFilter(src.FieldNo("S2"), '=%1', 'A');
dt.CopyRows();
end;
Wie CopyFields ist CopyRows ein Massenvorgang. Es bietet eine leistungsstarke Ausführung, indem nur eine einzige SQL-Anweisung für die gesamte Operation ausgeführt wird, anstatt mehrere Operationen pro Zeile auszuführen. Messungen haben eine ca. 50-fache Steigerung der Leistung mit einer DataTransfer-Lösung im Vergleich zu einer Record-API-Lösung gezeigt.


