Verwenden von Datenbankkomponenten in einer DLL

  • Um Datenbankkomponenten in einer DLL verwenden zu können, muss im DLL-Projekt eine Form (zur Laufzeit erzeugt!) mit den Datenbankkomponenten vorhanden sein.
  • BCB starten und im Menü ‘Datei->Neu->DLL Experte’ wählen
  • Datei->Neu->Neues Formular wählen
  • auf das Formular die benötigten Datenbankkomponenten ziehen (im hier vorliegenden Bsp. wird mit den MySQLDAC-Komponenten gearbeitet, es funktioniert aber auch mit beliebigen anderen)
  • *.cpp der DLL (nicht die der Form!):
  • #include <vcl.h>
    #include <stdio.h>
    #include <windows.h>
    #pragma hdrstop
    #include "DLLDBForm.h"
    //---------------------------------------------------------------------------
    //USEFORM("DLLDBForm.cpp", frmDLLDBForm);
    //---------------------------------------------------------------------------
    //Funktion die exportiert wird
    //---------------------------------------------------------------------------
    extern "C" __declspec(dllexport) int ExportDBValue();
    
    #pragma argsused
    int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
    {
        return 1;
    }
    
    int ExportDBValue()
    {
        int iReturnWert; // Rückgabewert
    
        TfrmDLLDBForm *DBForm = new TfrmDLLDBForm(NULL); // Form zur Laufzeit erzeugen
    
        DBForm->mySQLQuery1->Close();
        DBForm->mySQLQuery1->SQL->Clear();
        DBForm->mySQLQuery1->SQL->Add("select id from table");
        DBForm->mySQLDatabase1->Open();
        DBForm->mySQLQuery1->Open();
    
        DBForm->ShowModal(); // Form zum Test mit anzeigen
    
        // Beispiel-int-Wert aus Spalte "id" lesen
        iReturnWert = DBForm->mySQLQuery1->FieldByName("id")->AsInteger;
    
        delete DBForm; // Form nach der Benutzung wieder zerstören!!!
    
        return iReturnWert; // Wert zurückgeben
    }
    
  • *.lib der DLL in das Projekt einbinden, in dem die DLL verwendet werden soll
  • *.cpp eines Beispielprogrammes, das die Funktion ExportDBValue() der DLL aufruft:
  • #include <vcl.h>
    #pragma hdrstop
    #include "Unit1.h"
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    
    TForm1 *Form1;
    //Funktion, die aus der DLL importiert wird
    extern "C" __declspec(dllimport) int ExportDBValue();
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
    {
    }
    
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
        int r;
        r = ExportDBValue();
        Edit1->Text = IntToStr(r);
    }
    

BLOBStream (Bild) aus einer Datenbank Laden/Speichern

  • ein Bild in eine Tabelle (Table-Element) mit der Spalte “PICTURE” speichern
void __fastcall TForm1::SaveImageBtnClick(TObject *Sender) 
{ 
    if (OpenDialog1->Execute() == false)
    {
        Table->Active = true; 
        Table->Append(); 
        Table->FieldByName(&quot;Name&quot;)->AsString = ExtractFileName(OpenDialog1->FileName); 

        TBlobField* blobField = dynamic_cast <TBlobField*-> (Table->FieldByName(&quot;PICTURE&quot;)); 
        if (blobField) blobField->LoadFromFile(OpenDialog1->FileName); 
        Table->Post(); 
    }
}
  • ein Bild aus einer Tabelle laden (Spalte “PICTURE”)
void __fastcall TForm1::LoadImageBtnClick(TObject *Sender) 
{ 
    TBlobField* blobField = dynamic_cast <TBlobField*-> (Table->FieldByName(&quot;PICTURE&quot;)); 
    if (blobField == NULL)
    {
        Table->Active = true; 
        TMemoryStream* memStream = new TMemoryStream; 
        blobField->SaveToStream(memStream); 
        memStream->Position = 0; 
        Image1->Picture->Bitmap->LoadFromStream(memStream); 
        delete memStream; 
    }
}

Daten aus einer Datenbank-Tabelle in einem ListView anzeigen

  • Im Beispiel liegen die für den Datenbankzugriff benötigten Komponenten (TDatabase, TQuery) auf einem DataModul (TDataModule).
#include "DataModule.h"

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    SqlQuery(true, "SELECT * FROM TabellenName"); // Daten holen, siehe Beispiel weiter oben

    ListView->Items->Clear(); // Listviel erstmal leeren

    // alle Datensätze aus der Query in das ListView holen
    for (int i=0; i<DataModule->SQLQuery->RecordCount; i++)
    {
        ListItem = ListView->Items->Add();

        // fiktiven Namen und Alter ins Listview übertragen
        ListItem->Caption = DataModule->SQLQuery->FieldByName("name")->AsString);
        ListItem->SubItems->Add(DataModule->SQLQuery->FieldByName("alter")->AsString);

        // zum nächsten Datensatz springen
        DataModule->SQLQuery->Next();
    }
}

Daten von einer TQuery holen

AnsiString sTempString = SQLQuery->FieldByName(&quot;Spaltenname&quot;)->AsString;
float fZahl = SQLQuery->FieldByName(&quot;Spaltenname&quot;)->AsFloat;
int iWert = SQLQuery->FieldByName(&quot;Spaltenname&quot;)->AsInteger;

oder

AnsiString sTempString = SQLQuery->Fields->Fields[SpaltenNummer]->AsString;
float fZahl = SQLQuery->Fields->Fields[SpaltenNummer]->AsFloat;
int iWert = SQLQuery->Fields->Fields[SpaltenNummer]->AsInteger;

Arbeit mit TQuery und SQL

  • Um die Arbeit mit SQL Strings und den TQuery-Objekten zu vereinfachen sollte man sich eine Funktion schreiben, an die nur noch der SQL-String und der Typ der Rückgabemenge übergeben wird.
// &quot;true&quot; für Abfragen mit Rückgabemenge
SqlQuery(true, &quot;SELECT * FROM tablename&quot;);

// &quot;false&quot; für Abfragen ohne Rückgabemenge
SqlQuery(false, &quot;INSERT INTO tablename (col1, col2, ...) VALUES (0, 'String', NULL)&quot;);

void TDataModule::SqlQuery(bool QueryType, AnsiString Sql)
{
    SQLQuery->Close();
    SQLQuery->SQL->Clear();
    SQLQuery->SQL->Add(Sql);

    if (QueryType) SQLQuery->Open();
    else SQLQuery->ExecSQL();
}

Beispiel für einen Datenbankzugriff mit MySQLDAC-Komponenten

Auf eine Form eine mySQLDatabase, mySQLQuery, Datasource, DBGrid und einen DBNavigator ziehen und im Objektinspektor folgendes einstellen:

mySQLDatabase1->DatabaseName = beliebiger Name
mySQLDatabase1->Host = IP-Adresse des mySQL-Servers;
mySQLDatabase1->Port = 3306;
mySQLDatabase1->UserName = ein Username;
mySQLDatabase1->UserPassword = gültiges Passwort;
mySQLDatabase1->Active = true;

mySQLQuery1->DataBase = mySQLDatabase1
mySQLQuery1->sql: SELECT * FROM TabellenName
mySQLQuery1->Active = true;

DataSource1->DataSet = Query1

DBGrid1->DataSource = Datasource1

DBNavigator->DataSource = Datasource1

Beispiel für einen Datenbankzugriff mit BDE-Komponenten

Auf eine Form eine Database, Query, Datasource, DBGrid und einen DBNavigator ziehen und im Objektinspektor folgendes einstellen:

Database1->Aliasname = BCDemos
Database1->DatabaseName = TestDB
Database1->LoginPrompt = false
Database1->Active = true;

Query1->DatabaseName = TestDB
Query1->sql: SELECT * FROM animals
Query1->Active = true;

DataSource1->DataSet = Query1

DBGrid1->DataSource = Datasource1

DBNavigator->DataSource = Datasource1