Abschied von der BDE: Datenbankzugriff mit FireDAC

Keine Zeit? Hier die Kurzversion in 30 Sekunden.
- Embarcadero hat AnyDAC übernommen und als FireDAC integriert; seit XE5 (September 2013) ist es in den Editionen enthalten, für XE4 gab es das Add-on.
- Die BDE ist lange abgekündigt, nur 32 Bit und macht unter neueren Windows-Versionen Ärger.
- Kernkomponenten:
TFDConnectionundTFDQuery, Treiber über den ParameterDriverID, Abfragen mit Parametern überParamByName.- Gegenüber dbExpress ist FireDAC deutlich bequemer, weil es direkt bearbeitbare Datasets liefert.
- Migration schrittweise: Komponenten tauschen, dann Datentypen und Transaktionen prüfen.
Wer seit den Zeiten von Delphi und C++Builder 5 oder 6 Anwendungen pflegt, hat sie vermutlich noch irgendwo: die Borland Database Engine. TTable, TQuery, TDatabase und ein BDE-Alias, den man im BDE Administrator angelegt hat. Die Technik ist seit Langem abgekündigt, funktioniert aber in vielen Altprojekten, und genau das macht den Abschied unbequem. Mit XE5 ist nun ein guter Zeitpunkt, ihn anzugehen, denn Embarcadero liefert mit FireDAC einen Nachfolger mit.
Warum die BDE weg muss
Die BDE gibt es nur als 32-Bit-Technik. Sie braucht eine eigene Installation mit Konfigurationsdateien, die unter neueren Windows-Versionen gern an Rechten und Pfaden scheitert, und sie wird nicht mehr weiterentwickelt. Neue Datenbankversionen und Treiber bekommt man nicht mehr. Jede Anwendung, die daran hängt, hat eine Altlast im Gepäck, und die wird nicht kleiner. Das ist kein Drama, solange alles läuft, aber ein ungutes Gefühl bei jeder Windows-Umstellung.
Was FireDAC ist
FireDAC hieß bis Anfang des Jahres AnyDAC und stammt von DA-SOFT. Embarcadero hat das Produkt übernommen und in die Entwicklungsumgebung integriert. Für XE4 gab es das als Zusatz, mit XE5 ist es Teil der Editionen. Der Ansatz ist eine einheitliche Schicht über vielen Datenbanken (unter anderem Firebird, InterBase, MySQL, Oracle, SQL Server, SQLite, PostgreSQL), die direkt auf die Client-Bibliotheken zugreift, ohne weitere Zwischenschicht. Die Ausgabe sind normale Datasets, die man aus der BDE-Zeit kennt.
Einen Preis hat das Ganze natürlich: Man tauscht die Abhängigkeit von der BDE gegen eine von den Client-Bibliotheken der jeweiligen Datenbank. Beim Ausliefern muss die passende DLL (bei Firebird die fbclient.dll) in der richtigen Bitbreite neben der Anwendung liegen, sonst scheitert schon das Verbinden. Das ist aber ein überschaubares Problem, verglichen mit der BDE-Installation samt Konfigurationsdatei, die man früher mitgeliefert hat.
Der erste Zugriff
Auf das Formular kommen ein TFDConnection und ein TFDQuery, dessen Connection auf die Verbindung zeigt. Statt eines Alias gibt es Parameter, und der wichtigste ist DriverID:
void __fastcall TForm1::VerbindenClick(TObject *Sender)
{
FDConnection1->Params->Clear();
FDConnection1->Params->Add("DriverID=FB");
FDConnection1->Params->Add("Database=C:\\Daten\\kunden.fdb");
FDConnection1->Params->Add("User_Name=SYSDBA");
FDConnection1->Params->Add("Password=masterkey");
FDConnection1->Connected = true;
}Das Beispiel nutzt Firebird, mit anderen Treibern ändern sich DriverID und einige Parameter, etwa Server bei Netzwerkdatenbanken. Die Client-Bibliothek des Herstellers muss auf dem Rechner vorhanden sein; wo sie liegt, lässt sich über eine Treiber-Link-Komponente festlegen. Zugangsdaten gehören übrigens nicht in den Quelltext, das Beispiel dient nur der Kürze. Für eine Abfrage mit Parameter:
void __fastcall TForm1::SuchenClick(TObject *Sender)
{
FDQuery1->Close();
FDQuery1->SQL->Text = "select NAME, ORT from KUNDEN where ORT = :ort";
FDQuery1->ParamByName("ort")->AsString = EditOrt->Text;
FDQuery1->Open();
Memo1->Lines->Clear();
while (!FDQuery1->Eof) {
Memo1->Lines->Add(FDQuery1->FieldByName("NAME")->AsString);
FDQuery1->Next();
}
}Parameter mit ParamByName sind der richtige Weg. Wer SQL aus Strings zusammensetzt, öffnet SQL-Injection und hat Ärger mit Anführungszeichen und Datumsformaten. Für Änderungen ruft man statt Open() die Methode ExecSQL() auf.
Vergleich zu dbExpress
dbExpress war der erste Versuch, die BDE zu ersetzen, und taugt für den einfachen Fall. Die Datasets sind aber unidirektional und nicht bearbeitbar. Für komfortable Oberflächen braucht man zusätzlich TDataSetProvider und TClientDataSet, die Kette ist also länger. FireDAC liefert dagegen Datasets, die sich direkt an Datenfelder und Grids binden und bearbeiten lassen, ähnlich wie man es aus der BDE gewohnt war. Das erleichtert den Umstieg erheblich, denn Oberflächen mit datensensitiven Komponenten bleiben weitgehend unverändert, wenn man nur die Datenquelle austauscht. Bei dbExpress hätte ich dagegen oft die halbe Datenschicht umbauen müssen. Dazu kommt Unterstützung für 64 Bit und mehrere Zielplattformen.
Schrittweise migrieren
Ein Big-Bang-Umbau ist selten sinnvoll. Mein Vorgehen wäre:
- Eine Verbindung pro Datenmodul auf
TFDConnectionumstellen, nicht pro Formular. TQueryundTTablenach und nach durchTFDQueryundTFDTableersetzen und die SQL-Texte auf Parameter prüfen.- Nach jedem Schritt die Anwendung gegen echte Daten testen.
Fallstricke gibt es vor allem an zwei Stellen. Erstens beim Mapping von Datentypen: Zahlen mit Nachkommastellen, Datums- und Textfelder werden je nach Datenbank anders abgebildet, und was die BDE als Float lieferte, kann jetzt als Währung oder BCD ankommen. Berechnungen und Formatierungen sollte man danach kontrollieren. Über die Format-Optionen der Komponenten lassen sich Zuordnungsregeln anpassen. Zweitens bei Transaktionen: Die BDE hatte eigene Vorstellungen von automatischer Bestätigung. Bei FireDAC startet man sie bewusst mit StartTransaction(), schließt mit Commit() ab und macht bei Fehlern Rollback(). Ohne ausdrückliche Transaktion arbeitet die Verbindung im Auto-Commit, was in Altcode, der mehrere Schritte zusammenfassen wollte, zu halb geschriebenen Daten führen kann.
Meine Meinung
FireDAC ist der erste Nachfolger, bei dem ich nicht das Gefühl habe, etwas Schlechteres als die BDE einzutauschen. Wer noch BDE-Anwendungen pflegt, sollte den Umstieg einplanen, bevor ein Betriebssystemwechsel ihn erzwingt. Der Aufwand hängt davon ab, wie sauber die Datenzugriffe getrennt sind. Je mehr SQL und Komponenten über das Projekt verstreut sind, desto länger dauert es, aber der Weg ist begehbar.
Beitragsbild: eigene Collage mit Logos von Wikimedia Commons (Embarcadero-Logo: Jc86035, CC BY-SA 3.0); die Marken gehören ihren Inhabern. Die Collage steht ebenfalls unter CC BY-SA 3.0.
Christian Ackermann
Softwareentwickler (C++, C, Java, C#) aus der Oberpfalz, bloggt seit 2001 über Linux, Technik und Kochen.