![]() |
Datenbank: alle von Zeos untersützten DB • Zugriff über: Zeos
Crystal Reports XI + Delphi und unterschiedliche Datenbanken
Hi,
ich hab ein recht kompliziertes Problem mit Crystal Reports und Delphi. Wir haben eine recht große Applikation in Delphi (Win32) die intern die Zeos Komponenten benutzt. Sinn der Sache ist der, dass man momentan nur eine embedded Firebird Datenbank einbindet (für Einzeplplatz-Versionen) oder einen Firebird-Server (für Netzwerk-Versionen mit mehreren Clients). Später sollen dann MSSQL und Oracle dazukommen. D.h. Die Application ist so ausgelegt, dass man im Prinzip jede Datenbank, die Zeos untersüttzt, auch anbinden kann. Im Programm drin gibt es ein Benutzersystem, hunderten von Zugriffsrechen usw. auf bestimmte Teile des Programms und damit auch auf die Datenbestände/Tabellen an sich. Jetzt sollen mit Crystal Reports diese Daten ausgewertet werden. Das sind ca. 200 Auswertungen und Statistiken, die ich schon alle erstellt und die auch schon mit dem Programm zusammen ausgeliefert werden. Dazu hab ich die Delphi Komponente für CRXI verwendet, da gibts TCrpe und TCrpeDS. Und zwar hat man bei CR ja die Möglichkeit, über integrierte Treiber oder über ODBC, JDBC usw. eine Datenbank anzubinden. D.h. Crystal kann in dem Fall direkt mit der verbunden Datenbank über SQL kommunizieren. In meinem Fall hab ich ja aber keine Ahnung welche Datenbank angebunden ist, zumal noch die Zugriffsgeschichte reinfällt. D.h. ich hab für jede Tabelle ein *.ttx File angelegt, das die Feldgröße, Feldname usw. beinhaltet. Diese Dateien kann man als eine Felddefinitionsdatei in einen Report laden und kann damit auch einen kompletten Report erstellen. Erst wenn der Report in einem Programm per TCrpe Komponente geladen wird, wird dynamisch die Datenquelle zugewiesen. Dazu stellt die Crpe Komponente alle Tabellen, die in dem Report vorkommen, zu Verfügung, dann kann man einfach ein vorhandenes TDataSet damit per DataPointer damit verbinden. Also hab ich z.B. eine Tabelle MY_DATA in dem Report defniert, muss ich zuerst eine ZQuery erstellen, ein "SELECT * FROM MY_DATA"; ausführen und das daraus resultierende Dataset in ein TCrpeDS Object packen. Dieses repräsentiert sozusagen die Datenquelle für den Report und diese kann ich nun der Tabelle die mir TCrpe ausgibt, zuweisen (tableByName('MY_DATA').DataPointer := myTcrpeDSobj). Somit ist es für mich beim Report-Erstellen und auswerten völlig schnurz, welches DBMS dahinter steht, die Applikation gibt mir ja immer das passende Dataset zurück. Manchen wird es schon aufgefallen sein: Wenn ich einen Report erstellen muss, der zwei Tabellen braucht die per INNER JOIN z.B. verknüpft werden bedeutet das in meinem Fall, dass ich zuerst ein SELECT * FROM tbl1 mache und das Dataset zuweise, dann ein SELECT * FROM tbl2 mache und das Dataset wiederum zuweise. Crystal macht jetzt den INNER JOIN selbst aus den zwei Datasets die es bekommt. Bei 100000 x 10000 Datensätzen dauert das eine halbe Ewigkeit. Das Problem liegt daran, dass Crystal - wenn es eine SQL fähige Datenbank hat - direkt einen SQL INNER JOIN Befehl zusammenbaut und den an die Datenbank schickt. Genau DAS ist hier nicht der Fall - es geht technisch einfach nicht. Und genau hier muss ich jetzt ansetzen... Es wird langsam untragbar, das eine Auswertung, die über SQL eigentlich 2-3 Sekunden braucht, bei unseren Kunden oft über 15-30 Minuten dauert. Da ich nicht nur richtige Server anbinden muss, sondern auch eine embedded Firebird Datenbank habe, die schon durch das Programm geöffnet ist, fällt ein direkter Zugriff von CRXI auf die Datenbank weg - ganz zu schweigen von den ganzen Zugriffsrechen usw. Ein Zugriff über diese *.ttx Files ist aber auch nicht tragbar wegen der Geschwindigkeit. D.h. ich müsste eine Möglichkeit schaffen, dass CRXI direkt seine SQL Statements an die Applikation senden kann, diese an die Datenbank schickt und das Resultset wieder an Crystal gibt. Daher wäre meine Idee: Die Applikation bekommt eine Netzwerkschnittstelle verpasst, so dass ein zusätzlicher Thread auf Port 5678 hört. Dann schreibe ich einen ODBC-Treiber, der sich auf diesen Port verbinden kann und entsprechende Statements an die Applikation weitergeben kann. So kann ich in Crystal diesen ODBC Treiber einbinden und damit arbeiten, SQL Statements die CRXI an den ODBC Treiber sendet, landen über die TCP Verbindung in dem Thread der Applikation, hier wird das Statement an die Zeos Library weitergegeben und das Resultset über TCP an den ODBC Treiber zurückgeben. Damit hätte ich alle Voraussetzungen: + Crystal hat eine (vorgetäuschte) SQL Datenbank + Statt 10 Statements bei 10 Tabellen die verknüpft werden müssen, wird nur noch ein SQL Statement erzeugt + die Datenbank übernimmt dei Datenverknüfung und CRXI muss das nicht mehr selbst machen. So, zu dieser Vorgehensweise hätte ich ein paar Fragen: 1. Was halten die eingefleischten Datenbanktechniker hier von dieser Idee? 2. Hat jemand einen besseren Vorschlag? 3. Hat jemand mal einen ODBC Treiber entwickelt? ich hab mich damit mal etwas beschäftigt, sieht recht heftig aus, vor allem weil ich ja noch ein eigenes Protokoll entwickeln muss, das die Kommunikation zwischen ODBC Treiber und Applikation herstellt. 4. Sind ODBC Treiber überhaupt zu empfehlen? Irgendwo hab ich gelesen die sind veraltet - aber einen Ersatz hab ich noch nicht gefunden. 5. Angenommen ich habe eine embedded Firebird Datenbank, kann ich maximal eine ZConnection erstellen. ich hab aber die Applikation und meinen zusätlichen Thread für die TCP Verbindungen der die SQL Statements an die Datenbank schicken muss - geht das überhaupt? Ich müsste dann eine ZConnection über zwei Threads benutzen, soweit ich weiß sind die Dinger nicht threadsave - muss ich mir hier meine eigenen Locks einbauen? 6. Lässt sich per ODBC irgendwie die Syntax der generierten SQL Statements festlegen? Zum Beispiel versteht eine Oracle Datenbank nicht alles was Firebird versteht - und umgekehrt. Wie kann ich Crystal sagen wie das SQL Statement aufgebaut sein muss? Oder benötige ich da einen Wrapper im der Applikation die mir den SQL String analysiert und auf die gerade aktive Datenbank umschreibt? -> Gibt es dafür schon Komponenten? die Zeos haben so etwas soweit ich weiß nicht. |
Re: Crystal Reports XI + Delphi und unterschiedliche Datenba
So wie du dir das ausgedacht ist ist es meiner Meinung nach nur schwer lösbar und wenn es gehen sollte wird es sicher sehr fehleranfällig sein, dh. es darf wirklich nichts falsch laufen, damit ein Ergebnis vorhanden ist.
Warum machst du nicht einfach einen Script (den Ihr vorgebt und der Anwender gegebenenfalls ändern kann), wobei ich aber nicht den Umfang deiner Anwendung bzw. Datenbank kenne, der die entsprechenden Tabellen mittels SQL-Abfragen in dein gewünschtes Tabellenformat exportieren kann (BDE, ADO, DBF-nativ, etc. etc.) und auf die der CRXI zugreifen kann? Dann wärst du von allen Schwierigkeiten für Zugriffsrechte, Schnittstellen und zusätzlichen Client-Lizenzen entbunden. Grüssle Gremlin |
Re: Crystal Reports XI + Delphi und unterschiedliche Datenba
Nunja, es sind rund 150 Tabellen und 200 Auswertungen, und die Auswertungen sollen vom Endbenutzer erweitert bzw. neue hinzugefügt werden.
D.h. ich müsste generell für jeden Report, der aufgerufen wird, den kompletten Datenbestand in eine zweite Datenbank kopieren, z.B. in eine embedded Firebird Datenbank und beim Aufruf des Reports über den Firebird ODBC Treiber drauf zugreifen. Da es sich hier um recht große Datenbanken handeln kann ist dies wohl von der Geschwindigkeit her genauso wie es jetzt auch ist :/ Als Notlösung die auf deinen Vorschlag passt, könne ich mir vorstellen dass jeder Report um eine gleichnamige INI Datei erweitert wird in der drin steht: "Brauche Tabelle: foo_1, bar_2, ..." Wird der Report aufgerufen wird eine firebird datenbank angelegt in die ich lediglich die angegebenen Tabellen kopiere. Das ist allerdings nicht besonders kundenfreundlich, über einen eigenen ODBC Treiber wären wirklich alle Metainfos aus der richtigen Datenbank in CRXI zu Verfügung, d.h. $Kunde kann sich bequem per Drag&drop seinen Report zusammenstellen. Weiterer Grund der dagegen spricht, ist dass die Datenbankoperationen dann alle lokal ausgeführt werden, obwohl eigentlich 30 Meter weiter ein besser ausgerüsteter, extra angeschaffter Datenbankserver steht... Trotzdem danke für den Ansatz, an eine lokale Datenbank hatte ich so noch nicht gedacht, vielleich lässt sich das wirklich vorerst mal so wie oben beschrieben umsetzen. Kann vielleich noch einer was speziell zu den ODBC Fragen sagen? :) |
Re: Crystal Reports XI + Delphi und unterschiedliche Datenba
Würde einen ähnlichen Vorgehen wie Gremlin empfehlen.
Ignorier die SQL-Fähigkeit von CR und befüll es selbst mit deinen schon passenden Daten (von denen du selbst weist wie du diese trotz Rechtevergabe und Multi-DB-Support am besten bestimmst). CR sollte auch ohne den Umweg über Textdateien mittels "virtueller Datenanbindung" befüllbar sein. Einen eigenen Datenbanktreiber (ODBC) zu schreiben der wiklich full ODBC-Complient ist wird vermutlich bis er wirklich funktioniert (die Probleme liegen im Detail) einige Mannmonate arbeit verursachen, wenn nicht sogar Mann-Jahre. |
Re: Crystal Reports XI + Delphi und unterschiedliche Datenba
Zitat:
Genau aus diesem Grund brauche ich _unbedingt_ die Möglichkeit, Datenbankoperationen (Joins, gruppierungen usw.) auch von einer Datenbank ausführen zu lassen. |
Re: Crystal Reports XI + Delphi und unterschiedliche Datenba
@cytronix
Du wirst nicht alle 200 Tabellen für eine einzelne Auswertung benötigen. Du erstellst als Grundlage für jede Auswertung einen Script, in dem deine Auswertungsergebnisse Platz finden (zb. jeweils die Kunden und die Jahreszahlen für eine einfache Umsatzstatistik, ergo 2 Tabellen), die dein CRXI nur als "dummer" Reportgenerator anzeigen muss. Dazu solltest du VOR der Auslieferung an den Kunden, einen passenden Report für diese Daten erstellen (Tabellen zu neuem Report zufügen, schnell verknüpfen, Formeln setzen und ein wenig auf dem Formular die Felder hin und herschieben bis es passt). Wenn dann in deinem Programm dieses Modul ausgeführt werden soll, rufst du einfach den Script auf, der wiederum die angegebenen zwei Tabellen exportiert (wobei die beiden Tabellen natürlich für sich betrachtet eine eigene Auswertung ergeben, die der CRXI dann nicht mehr ausführen muss). Sollte diese Tabellenerstellung geklappt haben, so rufst du nur den CRXI mit der Angabe des passenden Reports auf und freust dich der Ausgabe. Auf keinen Fall exportierst du stur nur die Tabellen die der CRXI vielleicht für seine Auswertung benötigen könnte. Du machst die Auswertung mit deinem Script, ist ja auch einfacher wir mit dem CRXI und du benötigst keine zusätzliche Verbindung zur Datenbank (sprich Lizenz) Wie du auf eine lokale Auswertung der Daten kommst kann ich nicht nachvollziehen. Lies es einfach noch einmal durch :-D Gruss Gremlin PS: So eine einfache Auswertung über Script dauert auch nicht viel länger als direkt mit Delphi. |
Re: Crystal Reports XI + Delphi und unterschiedliche Datenba
hm ok, ich versuchs anders zu erklären:
Kunde hat Programm + CRXI Kunde möchte CRXI öffnen Datei neu, Datenbank auswählen, Verkünpfungen/Gruppierungen einrichten, Felder rüberziehen, eine Vorschau erstellen, abspeichern neuen Report im Programm eintragen Auswerten drücken. Zur Not kann ich ja z.B. wie schon erwähnt eine INI Datei hinzufügen in der ein paar Infos untergebracht sind. Tatsache ist aber, dass sämtliche Verknüfpungen, Gruppierungen usw. in CRXI eingestellt werden müssen. |
Re: Crystal Reports XI + Delphi und unterschiedliche Datenba
Ok, der Kunde kann mit CR XI (eigentlich auch ohne dein Programm) vollkommen selbstdefinierte Reports sich anlegen. Dann ist er auch selbst dafür verantwortlich dies so durchzuführen das seine Performance passt. Hier würde ich mir nicht den Schuh anziehen ihm hier mit teuer selbstimplementierter SW (ODBC-Treiber) die Mängel/Unvermögen von CR hier "vorrauszusehen" was nun die beste und schnellste Abfrage ist. Ich würde ihm anbieten mit eigener Implementierung (ohne direkte DB-Zugriffsmöglichkeiten von CR) diesen Report zu realisieren. Übernimmst du auch die Garantie bei einem CR-Fehler welche die Datenbank löscht hier gerade zu stehen?
|
Re: Crystal Reports XI + Delphi und unterschiedliche Datenba
Boh, wiso schreib ich eigentlich so viel und es versteht trotzdem keiner?!
Es gibt einen Grundsatz an Auswertungen die schon dem Programm beiliegen. und entweder bekommt der Kunde gegen Entgelt zusätzliche Auswertungungen oder er erstellt diese selbst. Aber ALLE Auswertungen müssen vom Programm aus geöffnet und angezeigt werden. Ich kann also keinem sagen, hier kümmer dich mal selbst wie es mit der Anbindung aussieht, außerdem muss die Datenbankverbindung IMMER übers Programm laufen - siehe embedded Datenbanken & Rechte wie ich es oben geschildert hab. Ich wiederhole es aber gern: Die embedded Datenbank ist während das Programm läuft schon geöffnet. Selbst wenn ich beim Kunden einen Firebird ODBC Treiber installiere, selbst wenn er es hinbekommt eine Verbindung einzurichten kann er die Auswertung nicht ausführen, da die Datenbank gelockt ist! Ich wollte hier über ein Problem diskutieren welches genau diese Randbedingungen hat: Datenverbindung geht übers Programm (tuts jetzt auch schon über die TCrpeDS Komponente, aber eben ohne SQL), unterschiedliche Datenbanken die angebunden sind (inkl. embedded Datenbanken) und was mir fehlt ist eine Möglichkeit, SQL Befehle an das Programm und damit an die Datenbank weiterzureichen. Deine Lösungsansätze sind schön, aber sie passen nicht auf mein Problem. Ich kann dem Kunden nicht die Lösungssuche für die Performance zuschieben, denn ich hab selbst 200 Auswertungen die eine bessere Performance nötig haben. Ich kann dem Kunden nicht die direkte Datanbankanbindung anbieten, denn unter Umständen arbeitet er mit einer embedded Datenbank. Und die Aussage " Mängel/Unvermögen von CR" kann ich so auch nicht im Raum stehen lassen, denn CR ist in erster Linie eine SQL Anwendung. Wenn ich mit einer SQL Anwendung Daten auswerten möchte, die nicht mit SQL angesprochen werden können, gehts halt nicht oder nur eingeschränkt. Word ist auch zum Schreiben von Text/Briefen gedacht, oder hast du schonmal versucht in Word eine komplizierte Excel-Tabelle umzusetzen? Der Grund, dass ich sowas versuche (muss), ist einfach die Randbedinung dass mehrere Datenbanken angebunden werden müssen, oft welche, von denen ich jetzt zum Zeitpunkt der Berichterstellung nicht mal weiß, dass sie irgendwann unterstützt werden. Vielleicht sind es ungeschickte Randbedingungen, aber sind sind nunmal da und dafür brauche ich eine Lösung, notfalls mit eigenen ODBC Treiber. Zitat:
|
Re: Crystal Reports XI + Delphi und unterschiedliche Datenba
Ich glaub du verstehst uns nicht ganz genau :-)
Jedes vernünftige Reportingtool kann auch ohne "normales" Dataset arbeiten, sprich man kann den Report mit "virtuellen" Datasets befüllen. Evtl. kann man auf diesen "virtuellen" Datasets den Kunden anpassungen vornehmen lass(Der ReportBuilder kann sowas z.B.). Wir haben als Lösung uns einen eigene auf unsere Anwendung abgestimmten Reportdesigner entwickelt. Damit haben wir 100% Kontrolle über die Reports und haben auch mit mehreren tausend Reportseiten keine Resourcenprobleme mehr. Und wir haben auch mehrere unterstützte DB's und auch DB's die bis zu 50 GB an Volumen haben. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:28 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz