Nach dem Wechsel zu FireDAC habe ich Probleme, diesen Code für MSSQL / Oracle zu verwenden:
%Vor% AKey und S sind beide Strings.
Die Open-Anweisung gibt einen Fehler
beim Verbinden mit einer MSSQL- oder Oracle-Datenbank; nicht beim Verbinden mit FireBird.
Nach dem FetchParams
ist DataFormsettings.params[1].datatype
immer ein ftString
.
Wenn ich
ersetze %Vor%mit
%Vor% ... die Open-Anweisung enthält keine Fehler. Ich dachte, das hätte es gelöst, obwohl ich den Fehler nicht wirklich verstanden habe. Nach allem sollten dies alle Delphi-String-Typen sein ...
Aber jetzt scheitert die Zuweisung für Oracle (nicht FireBird oder MSSQL) in dem Sinne, dass ich 2-Byte-Zeichen zurückgegeben bekomme. S enthält:
Ich kann das z. B. mit
umgehen %Vor%für Oracle, aber (natürlich) wenn Sie die anderen zwei Datenbanktypen verwenden, die nicht funktionieren:
%Vor% Was fehlt mir hier? Insbesondere möchte ich nur die AsString-Retrieval / Zuweisungen zum Arbeiten bekommen.
Beachten Sie, dass Wenn Sie die AsString-Eigenschaft festlegen, wird die DataType-Eigenschaft im FireDAC TFDParam.AsString Dokumentation . Es scheint, als ob die Parameter-Wertzuweisung nur den Typ von ftString auf ftWideString umschaltet (wie durch den ursprünglichen Fehler angezeigt).
DataFormSettings
ist ein TClientDataSet
in einer Clientanwendung, die mit einer Serveranwendung verbunden ist, in der sich TDataSetProvider
und TFDQuery
befinden. Die Abfrage ist
Die Tabellen wurden wie folgt erstellt:
Feuervogel:
%Vor%Oracle:
%Vor%MSSQL:
%Vor% Ich habe überprüft, dass TT_VIEWDATA
korrekte Daten in allen Datenbanken enthält; Es ist eine lange Zeichenfolge, die CRLFs enthält:
Anmerkungen:
select * from NLS_database_PARAMETERS where parameter like '%CHARACTERSET%'
gibt NLS_CHARACTERSET=WE8MSWIN1252
und NLS_NCHAR_CHARACTERSET=AL16UTF16
SELECT dump(dbms_lob.substr(tt_viewdata,100,1), 1016), tt_viewdata FROM tt_formsettings
bestätigt, dass der CLOB ASCII-Bytes für die Codepage Win1252 enthält: Typ=1 Len=100 CharacterSet=WE8MSWIN1252: 5c,53,6f,66,74,77,61,72,65,5c,54,69,6d,65,54,65,6c,6c,5c,44,65,...
FieldByName().AsANSIString
liefert die gleichen Ergebnisse wie FieldByName().AsString
Weitere Informationen: Dies ist eine Legacy-Anwendung mit persistenten Felddefinitionen für DataFormsettings
TClientDataset
. TT_VIEWDATA
ist definiert als TMemoField
:
In einer kleinen Testapp (direkt verbunden mit Oracle; nicht Client-Server) ließ ich Delphi die Felddefinitionen hinzufügen und sagte dann:
%Vor%Wenn ich das in der Haupt-App verwende, funktioniert Oracle gut, aber dann bekomme ich 'Müll' für MSSQL.
Ich experimentierte auch mit dem Einrichten von Zuordnungsregeln für die Oracle-Verbindung wie (viele Variationen):
%Vor%aber das hat nicht geholfen.
Hier ist der Grund, warum es nicht funktioniert:
In FireDAC.Stan.Option
:
In der Tat können Probleme sein .
Die Lösung besteht darin, eine Zuordnungsregel hinzuzufügen, die dtWideHMemo
in dtMemo
konvertiert.
Danach funktioniert das Lesen und Schreiben in den CLOB .AsString
einwandfrei.
Wird als RSP-19600 im Embarcadero Quality Portal gemeldet.
Der Vollständigkeit halber: Da das in meiner anderen Antwort erwähnte Mapping nicht mehr aktiv ist, müssen Sie den Zugriff auf die Parameter mit .Value
anstelle von .AsString.
Dies ist keine definitive Lösung, siehe die letzten Anmerkungen vor den Codeblöcken. Es fühlt sich immer noch an wie ein Hack. Ich füge es der Frage nicht hinzu (als 'Versuche'), weil das letztendlich funktionieren würde.
Es gab zwei Dinge, und sie können beide mit den folgenden Änderungen umgehen:
FieldByName().AsString
retrieval / assigning funktioniert nicht Beachten Sie, dass ich durch Design-Time-Felddefinitionen in der gesamten Anwendung eingeschränkt bin, die alle drei Datenbanktypen verarbeiten müssen, insbesondere das DataFormSettingsTT_VIEWDATA
persistent-Feld ist ein TMemoField
.
Wenn Sie bei den am Ende der Frage genannten Tabellendefinitionen eine TFDConnection -> TFDQuery -> TDataSetProvider -> TClientDataSet
einrichten und die Felddefinitionen mit Alle Felder hinzufügen hinzufügen, hat DataFormSettingsTT_VIEWDATA
den Typ:
TMemoField
mit BlobType=ftMemoField
für FireBird
TMemoField
mit BlobType=ftWideMemoField
für MSSQL
TWideMemoField
mit BlobType=ftWideMemoField
für Oracle.
Manuelles Editieren von .DFM und .PAS, um das TWideMemoField
von% zurück auf TMemoField
zu setzen (nun, ich muss es nicht ändern, es ist Legacy-Code), wenn ich auch:
force BlobType=ftWideMemoField
für die Entwurfszeit TMemoField
s zur Laufzeit (Ich kann das in OnCreate in einem Elternteil tun, von dem alle meine Datenmodule abstammen);
behandelt den String-Abruf nur für Oracle als TEncoding.Unicode.GetString(FieldByName(SFormSettingsViewData).AsBytes)
.
Aber das ist immer noch nicht optimal. Mein Clientcode mit dem TClientDataSet muss nun wissen, um welche Art von Datenbank es sich handelt . Ich habe Mittel in der Client-App, um den Server dafür abzufragen.
Hier ist eine Beispiel-App mit diesen Änderungen:
uFireDacOracleBlob.pas
datei:
uFireDacOracleBlob.dfm
datei:
Hinweis: Die Tatsache, dass die Parameterzuweisung jetzt (auch) funktioniert, ist in der Datentypzuordnung ( FireDAC) Dokumentation:
Im Falle einer Ergebnismengenspalte definiert jede Regel eine Transformation eines Quelldatentyps, der von einem Treiber zurückgegeben wird, in einen Zieldatentyp, der von einer Anwendung bevorzugt wird. Im Falle eines Befehlsparameters definiert die Regel eine Umwandlung eines Zieldatentyps, der von einer Anwendung spezifiziert wird, in einen Quelldatentyp, der von einem Treiber unterstützt wird. Alle Regeln, mit Ausnahme der namensbasierten, funktionieren in beiden Fällen bidirektional.
Tags und Links oracle delphi firedac delphi-10.2-tokyo