Hi zusammen
@ stahli
Zitat:
FTblBildText : TTblBildText; // FBildDescribeTabelle : TBildDescribeTabelle;
FTblAlbum : TTbl_Album; // FKategoryTabelle : TKategoryTabelle;
Grundsätzlich trennt mein Programm
GUI und Datenhaltung. Letzteres fällt in die Zuständigkeit zweier Datenmodule; je eines für eine Verbindung zu
MySQL und eines, relativ neu in Arbeit, zu SQLite.
Die Datenbank selbst beinhaltet 12 Tabellen, wovon zurzeit nur 4 für Bild- und Textinhalte zuständig sind. Von drei dieser Tabellen gibt es innerhalb von TQueryresultClass Entsprechungen gleichnamiger Klassen.
Das obige Zitat gibt 2 Klassenfelder meiner gleichaufgebauten Klassen TQueryCMresultClass(FTblBildText ,FTblAlbum) und TQueryresultClass(FBildDescribeTabelle,FKategoryTa belle) wider.
Ich hänge hier mal noch TQueryCMresultClass an, um die Unterschiede zu verdeutlichen; diese bestehen ausschlieslich aus den in TQueryCMresultClass verwendeten kürzeren Tabellen- und Feldbezeichnern.
Natürlich wurde die SQLite_Datenbank auch mit den verkürzten Tabellennamen erstellt.
Zitat:
Haben sie noch eine Verbindung zur Datenbank oder nicht?
Wie bereits gesagt, handelt es sich hierbei um Klassenfelder, bzw. Unterklassen, die selbst keine Verbindung zur Datenbank haben.
Bei Select-Abfragen der TQuery-Komponente werden deren Resultate jeweils pro Datensatz über 3 Tabellen (ohne Zwischentabelle) in einer TQueryCMresultClass - Instanz festgehalten und diese einer Objectlist hinzugefügt. Dabei gibt es eine Besonderheit: Bilddaten werden bei der ursprünglichen Abfrage über mehrere Datensätze mit Ausnahme des Thumbnails vorerst nicht abgefragt, sondern erst, wenn sie zur Darstellung des Bildes benötigt werden.
Ein Ziel meiner Umstellung auf SQLite: von mir so genannte "Satelliten-DBs" zu erstellen(*). Das hat folgende Grund: Zur Zeit speichere ich die Bilder noch in einem Ordner auf Festplatte. Wenn die Dinger schliesslich in die
DB geschrieben werden, werden aus den Rohbildern nicht nur die Thumbnails, sondern auch gleichzeitig Bitmaps in Originalgrösse erstellt. Dabei sollten auch die Rohdaten ursprünglich mit in die
DB - und blähen diese zu gigantischer Grösse auf.
Und hier kommen dann meine "Satelliten-DBs" zum Zug: In ihnen werden die Rohdaten und Originalbitmaps zusammen mit einem Textfeld für den Namen und einem FK-Integer für das Album gespeichert. Diese Dinger bringen es auf Grössen von in etwa 25GB oder weniger, sind also eigentlich sogar als eine Art Rohdatenbackup zu gebrauchen und können Extern an beliebigen Orten gespeichert werden.
Wo sich diese "Satelliten-DBs" befinden, bestimmt letzlich der User über ein Optionen-Fenster.
Zitat:
Wie viele Daten verwaltest Du insgesamt in der Anwendung? Können alle Daten insgesamt im Speicher gehalten werden oder ist die Datenbank so groß, dass immer nur bestimmte Datensätze daraus abgeholt werden können?
Als ich das letzte mal gezählt habe, waren es ca. 13 000 Fotos.
Zitat:
Was ich generell nicht verstehe ist, dass Du Deine Businessklassenstruktur änderst, wenn Du die Datenbank wechselst oder die Tabellen in der Datenbank andere Namen haben.
An den Strukturen der Klassen ändert sich ja nichts - nur die verwendeten Namen sind kürzer geworden. Am Beispiel eines
SQL-Statements:
Delphi-Quellcode:
function TFDMySQLDml.DefineBildSQL3(Kath_Id: Integer) : String;
begin
Result := 'SELECT Bildtabelle.idBild as BildID, ' +
'bilddescribetabelle.BilddesribeID as BildDescribeId, ' +
'bilddescribetabelle.bildkatID as BildkatID, '+
'bilddescribetabelle.bildname as Bildname, ' +
'bilddescribetabelle.bildbeschreibung as Bildbeschreibung, '+
'bilddescribetabelle.bildlegende as bildlegende, ' +
'kategorien_tabelle.Kath_ID as KathID, ' +
'kategorien_tabelle.Kategorie as Kategorie, '+
'kategorien_tabelle_has_bilddescribetabelle.kategorien_tabelle_Kath_ID as TblKat_Id, '+
'kategorien_tabelle_has_bilddescribetabelle.BildDescribeTabelle_BilddesribeID as BildDesc_Id '+
'FROM ' +
'bildtabelle, bilddescribetabelle, ' +
'kategorien_tabelle_has_bilddescribetabelle, ' +
'kategorien_tabelle '+
'WHERE '+ {erste Tabelle}
'Kategorien_tabelle.Kath_Id = :Kath_Id '+
'AND '+ {zweite (Selektionstabelle) Tabelle wird mit erster verglichen}
'kategorien_tabelle_has_bilddescribetabelle.kategorien_tabelle_Kath_ID = Kategorien_tabelle.Kath_Id ' +
'AND '+ //--------------------
'kategorien_tabelle_has_bilddescribetabelle.BildDescribeTabelle_BilddesribeID = bilddescribetabelle.BilddesribeID ' +
'AND '+
'Bildtabelle.idBild = bilddescribetabelle.bildtabelle_idbild';
// Showmessage(Result);
end;
Das dürfte viel schwerer zu lesen sein als:
Delphi-Quellcode:
function TFDMySQLDml.DefineBildSQL3(Kath_Id: Integer) : String;
begin
Result := 'SELECT Tbl_Bild.idBild as BildID, ' +
'TblBildText.BilddesribeID as BildDescribeId, ' +
'TblBildText.bildkatID as BildkatID, '+
'TblBildText.bildname as Bildname, ' +
'TblBildText.bildbeschreibung as Bildbeschreibung, '+
'TblBildText.bildlegende as bildlegende, ' +
'TblAlbum.Kath_ID as AlbumId, ' +
'TblAlbum.Kategorie as Kategorie, '+
'TblAlbum_has_TblBildText.TblAlbum_Album_Id as TblKat_Id, '+
'TblAlbum_has_TblBildText.TblBildText_BilddesribeID as BildDesc_Id '+
'FROM ' +
'bildtabelle, TblBildText, ' +
'TblAlbum_has_TblBildText, ' +
'TblAlbum '+
'WHERE '+ {erste Tabelle}
'TblAlbum.Album_Id = :Album_Id '+
'AND '+ {zweite (Selektionstabelle) Tabelle wird mit erster verglichen}
'TblAlbum_has_TblBildText.TblAlbum_Album_Id = TblAlbum.Album_Id ' +
'AND '+ //--------------------
'TblAlbum_has_TblBildText.TblBildText_BilddesribeID = TblBildText.BilddesribeID ' +
'AND '+
'Bildtabelle.idBild = TblBildText.bildtabelle_idbild';
// Showmessage(Result);
end;
Wobei ich jetzt nur mal einiges ersetzen lassen habe - zu Demozwecken in einer neuangelegten, aber nicht gespeicherten
Unit.
Zitat:
Nach meiner Überlegung müsstest Du in Deinem Projekt das "Datenbankmodul" anpassen, aber nicht die Businessklassen.
Hmmm - was verstehst du genau unter Businessklassen? In der Schichtenprogrammierung gibt es meines Wissens folgende Ebenen//Schichten:
- Die Gui
- Die Logik- oder BusinessSchicht und schliesslich die
- Datenschicht (Datenmodul(e), DB-Verbindungen)
wobei die oberen nach unten durchgreifen dürfen, aber nicht umgekehrt. Wobei die Daten von der
Gui in einem Stringgrid dargestellt werden und das daher auf die Objectliste mit meinen Datenklassen zugreifen muss - das aber entspricht dem Modell(von oben nach unten).
Zitat:
Interfaces zu verwenden kann sinnvoll sein, muss es aber nicht in jedem Fall. Wenn Du damit noch keine Erfahrungen hast, würde ich die Projektstruktur erst mal überarbeiten und auf Interfaces verzichten. Da hängt noch einiges an notwendigen Anpassungen dran, die jetzt vielleicht unnötig verwirren würden.
Deshalb habe ich TQueryCMresultClass zuerst mal analog TQueryresultClass "händisch erstellt, indem ich TQueryresultClass als TQueryCMresultClass abgespeichert und verschiedene Namen durch <Suchen-Ersetzen> geändert habe.
Für Interfaces gibts erstmal ein (umfangreiches?) Testprogramm. Und erst Sachen, die da funktionieren und mir klar ist, warum sie das tun, können in meinem Programm eingebaut werden.
Zitat:
Statt dessen solltest Du eine Datenbankunit oder Datenbankklasse einführen, die alle Zugriffe auf die alte Datenbank kapselt - so dass Deine Anwendung nicht mehr die Datenbank selbst kennt, sondern nur noch Deine Datenbankunit oder Datenbankklasse.
Dann kannst Du eine neue Datenbankunit oder -Klasse aufbauen, die die selben Schnittstellen nach außen hat, aber intern auf eine andere Datenbank geht.
Das sind meine Datenmodule.
(*) abgesehen davon, dass es eigentlich unsinnig ist, als Anwendungsdatenbank einen Server wie
MySQL zu verwenden (Ausnahme:EmbeddedServer)
Gruss
Delbor