Fragen zu Datenbanken in Zusammenhang mit dem C++ Builder 2007
-
Hallo,
nach sehr langer Zeit arbeite ich wieder mit dem C++ Builder und bezüglich der Datenbankbehandlung kommen mir einige Fragen...
Ausgangssituation:
Eine Software die bislang relativ direkt mit Datenbankkomponenten hantiert, soll nun auf eine andere Datenbank umgestellt werden, möglichst so das der Anwender selbst entscheiden kann ob er mit einer Lokalen Datenbank wie bisher (MS Access) oder mit einer Serverdatenbank (voraussichtlich SQL Server) arbeiten will.Eine konkrete Installation muss aber zur Laufzeit nur mit jeweils einer der beiden Datenbanken klar kommen.
Bislang wurden auch die Datenbankkomponenten der VCL relativ intensiv genutzt. Die SQL Server Datenbank soll im gegensatz zur Accessdatenbank Transaktionen unterstützen.
Nun stellen sich mehrere Fragen:
1. Welche Möglichkeiten der Unterstützung seitens des C++ Builder kommen in Frage?
- Es geht hier u.a. um die Frage ob die Datenbankkomponenten bei mehreren unterschiedlichen Datenbanksystemen noch sinnvoll sind, oder ob eine gänzliche Trennung von UI-Elementen und DB-Elementen hier mehr Sinn macht...
2. Gibt es spezielles wegen den DB-Unterschieden zu berücksichtigen?
- Betrifft u.a. Transaktionen kontra keine Transaktionen, Unterschiede in der SQL-Syntax...Ich habe noch keinen Überblick über die flexibilität der Datenbankkomponenten unter dem C++ Builder und der VCL um z.B. sagen zu können wie DB-Neutral diese sind. Im Prinzip wäre auch eine grundsätzliche Trennung möglich (Ich persönlich bin auch aufgrund späterer Portierungsmöglichkeiten eher ein Freund von n-Tier Architekturen mit kompletter Trennung von UI- und DB-Logik, aber es gibt ja noch Faktoren wie bestehende Codebasis und Zeit). Ich habe hier in dieser Firma zwar überraschend viel Zeit für eine Umsetzung (sofern diese Sinn macht, und ggf. schon eine Zukunftsinvestition ist), wenn man eine sanfte Migration durchführen könnte wäre dies aber dennoch vielleicht vorzuziehen.
Eine Denkbare Lösung wäre eine Auslagerung der DB-Schnittstelle in zwei DLL's (eine für Access und eine für den SQL Server) mit einem gemeinsamen Interface. Die Frage ist nur ob es einfacher geht, und wieviel Sinn welcher Ansatz hätte.
cu André
-
Hallo
Dafür bietet sich als einfachstes die Verwendung von ODBC an. Der Builder ist bereits für eine Verbindung mit ODBC ausgerüstet, und die vorhandenen Komponenten bauen darauf auf. Alles was du dann machen must ist in der Windows Systemsteuerung einen ODBC-Alias (ähnlich wie ein Dateilink) entweder auf eine lokale Access-Datenbank oder auf den SQL-Server zu legen. Nachteil : ODBC ist veraltet und verlangsamt den Datenbankzugriff. Auch der Teil der Borland BDE, der für ODBC verantwortlich ist, ist veraltet und fehleranfällig.
Da aber das Borland Datenbank-Konzept erweiterbar ist, läßt sich der eigentliche Datenbank-Client austauschen, bei gleichbleibenden datensensitiven GUI- und Verwaltungsklassen. Es ist also schon möglich das du im Netz einen aktuellen und direkten Client findest, der auf Basis der abstrakten Borland-Datenbankschnittstelle den transparent Zugriff auf Access und MS SQL anbietet. Wir haben hier so ein Paket für MySQL, das funktioniert ganz gut.
Transaktionen sind eigentlich immer gut, für mehrstufige Bearbeitungen sollte das immer verwendet werden. Allerdings weiß ich nicht genau wie das vorhandene Interface vom Builder bereits Transaktionen unterstützt (außerhalb von manuellen SQL-Anweisungen).
Die Syntax zumindestens der Grundkommandos ist SQL-StandardABORT; BEGIN TRANSACTION; COMMIT;
Die Trennung von DB/Logik/GUI ist gut. Bei größeren Projekten lohnt es sich da mit TDataModul zu arbeiten, um nichtvisuelle Komponenten Formunabhängig und -übergreifend zu verwalten.
bis bald
akari
-
asc schrieb:
Eine Denkbare Lösung wäre eine Auslagerung der DB-Schnittstelle in zwei DLL's (eine für Access und eine für den SQL Server) mit einem gemeinsamen Interface. Die Frage ist nur ob es einfacher geht, und wieviel Sinn welcher Ansatz hätte.
So stark wirst Du es bestimmt nicht trennen müssen, dass doppelte Arbeit entsteht. Wenn die Anwendung bisjetzt beispielsweise DBExpress verwendet, brauchst Du doch nur das Verbindungsobjekt auszutauschen, die anderen Komponenten sind ja DB-unabhängig (siehe Akari's Post).
Transaktionen kontra keine Transaktionen: Hängt wohl davon ab, welches System Du verwendest. Allgemein könntest Du ja im Quelltext mit Transaktionen fahren und baust dazu zwei Transaktionen-Factories, die eine übergibt Dummy-Methoden für Access, die andere MSSQL-Transaktionsobjekte/Methoden.
Unterschiede in der SQL-Syntax: Soweit sollten diese beiden sich nicht unterscheiden, im allgemeinen verwenden ich immer ein Mischmasch aus:
- SQL-Anfragen auf gemeinsamen Nenner reduzieren (unter allen DB-Arten kompatibel)
- DB-Funktionen (Stringkonkatenation: || vs & vs + vs CONCAT()
- DB-Procs (da könntest Du evtl auch Deine Transaktionen verstecken)
- Factory-Objekte für spezielle DB-Info's (Katalog auslesen)
- Erbauermuster für komplexe SQL-Statements
-
Hallo,
akari schrieb:
...Die Syntax zumindestens der Grundkommandos ist SQL-Standard...
Die SQL-Syntax ist mir zum Glück geläufig, mit der VCL wiederum muss ich mich erst wieder anfreunden (Bin jetzt meinen 3ten Tag in einer neuen Firma, und hatte zuletzt mit dem Borland C++ Builder 4.0 Kontakt, als dieser aktuell war).
Ich würde nur gerne Vermeiden von vorne herein auf ein falsches Pferd zu setzen und einen gänzlich falschen Ansatz unter den C++ Builder zu wählen.
Mein derzeitiger Ansatz wäre alles DB-Spezifische aus der UI zu entfernen und in zwei DLL's zu stopfen (Eine für Access und eine für den SQL-Server). Alle Daten sowie alle Logik aus der UI zu nehmen und in eine separate Schicht zu verbannen. Sprich UI|Business Layer|Data Layer|DB. Das wäre mit Sicherheit sauberer als die derzeitige Lösung, aber auch die aufwendigste Lösung.
cu André
-
asc schrieb:
Mein derzeitiger Ansatz wäre alles DB-Spezifische aus der UI zu entfernen und in zwei DLL's zu stopfen (Eine für Access und eine für den SQL-Server).
Grundsätzlich richtig, aber da Access und der SQL-Server so ähnlich sind, ist das eventuell übertrieben. Im Prinzip stellt Access nur eine Teilmenge der Funktionalitäten eines SQL-Servers bereit. Wenn Du damit hinkommst...
Als Zugriffskomponenten würde ich die ADO-Komponenten nehmen. Eine TADOConnection unterstützt Transaktionen, so dass Du praktisch nur ein zusätzliches TADOConnection::BeginTrans() und ::EndTrans() für den SQL-Server brauchst. Der tückische Teil ist die Fehlerbehandlung... Bei Transaktionen kommst Du mit einem Rollback hin, bei Access musst Du Hand anlegen.
Wenn Du so lange nicht mit dem BCB gearbeitet hast: Neben try und catch, gibt es im BCB auch das __finally. Find ich gerade im Zusammenhang mit Datenbanken und Rollbacks sehr praktisch.
-
Joe_M. schrieb:
Als Zugriffskomponenten würde ich die ADO-Komponenten nehmen. Eine TADOConnection unterstützt Transaktionen, so dass Du praktisch nur ein zusätzliches TADOConnection::BeginTrans() und ::EndTrans() für den SQL-Server brauchst. Der tückische Teil ist die Fehlerbehandlung... Bei Transaktionen kommst Du mit einem Rollback hin, bei Access musst Du Hand anlegen.
TAdoConnection wurde wohl auch bislang verwendet. Nachtrag: TAdoConnection mit ADO über DAO wegen Tabellensperrungen (Sperren sollen wohl unter ADO nicht gehen?)
Und spätestens bei dem Unterschied Rollback<->Hand anlegen sehe ich, das eine Trennung vieleicht alleine schon aus Gründen der Lesbarkeit doch sinnvoll ist (Wobei man schauen könnte ob es auch einen "gemeinsamen Teil" gibt. Zudem ist noch nicht abzusehen ob es langfristig wirklich bei Access/SQL Server bleibt.
Joe_M. schrieb:
Wenn Du so lange nicht mit dem BCB gearbeitet hast: Neben try und catch, gibt es im BCB auch das __finally. Find ich gerade im Zusammenhang mit Datenbanken und Rollbacks sehr praktisch.
Also __finally werde ich mir sicherlich nicht angewöhnen. Hierzu gibt es in C++ andere Lösungen (RAII und Co) ohne auf Compilerspezifika zurückzugreifen.
cu André
-
Hm, zum Thema Tabellen sperren kann ich nichts sagen, habe ich bisher nicht benötigt...
Ok, unter dem Aspekt, dass weitere 'Transaktionsunfähige' DMBS dazu kommen können, macht es wohl tatsächlich Sinn für Access und den SQL-Server eigene DLLs zu verwenden. Dann hat man zumindest für beides schon mal eine Grundlage.
asc schrieb:
ohne auf Compilerspezifika zurückzugreifen.
Ja, dann müsstest Du in den DLLs allerdings auch komplett auf die VCL verzichten.
Ich hab mein Ziel erreicht, Du weißt, dass es das gibt und vielleicht kannst Du es ja doch mal brauchen.
Grüße Joe_M.
-
Dein Problem verlangt eigentlich nach so etwas wie DBExpress.
Zum Auslagern bieten sich aber vielleicht eher Packages an; das ist bei Delphi und C++Builder zuweilen etwas komfortabler.asc schrieb:
Also __finally werde ich mir sicherlich nicht angewöhnen. Hierzu gibt es in C++ andere Lösungen (RAII und Co) ohne auf Compilerspezifika zurückzugreifen.
Das will ich aber auch meinen