Blobs ins DB Speichern
-
geht alles irgentwie nicht ....
komisch ist, das nach
Stream2 = SQLComponents->SQLClientDataSet->CreateBlobStream(SQLComponents->SQLClientDataSet->FieldByName("BLOB"), bmReadWrite); Stream2->Write(Buffer, Bytes); int t = Stream2->Size;
t nicht die Größe des Bytes (Bytes des Buffers), sondern die Größe des BLOBS der bereits in der Datenbank ist hat.
Hat nich noch wer ne Idee was ich falsch machen könnte?
ich weiß nicht mehr weiter
-
Werfe mal einen Blick auf folgende Seiten:
http://www.bcbdev.com/faqs/faq94.htm
http://www.bridgespublishing.com/articles/issues/9809/How_can_I_use_BLOBs_with_C++Builder_.htm
-
Danke!
Ich habe den Code jetzt soweit:
AnsiString SQL1 = "select BLOB from TABLE where BLOBX ="; AnsiString DokuX = Edit1->Text; const AnsiString BrowserFile = "c:\\temp\\test.gif"; AnsiString Query1 = SQL1 + DokuX; AnsiString UserName = "Username"; AnsiString Password = "Password"; //Klasse mit benötigten SQL Komponenten if (SQLComponents == NULL) { SQLComponents = new TSQLComponents(NULL); } SQLComponents->SQLConnection->Params->Values["User_Name"] = UserName.c_str(); SQLComponents->SQLConnection->Params->Values["Password"] = Password.c_str(); // verbindung herstellen SQLComponents->SQLClientDataSet->CommandText = Query1.c_str(); SQLComponents->SQLConnection->Connected = true; SQLComponents->SQLClientDataSet->Active = true; // Feld bearbeiten SQLComponents->SQLClientDataSet->Edit(); TBlobField * blobField = dynamic_cast <TBlobField *> (SQLComponents->SQLClientDataSet->FieldByName("BLOB")); blobField->LoadFromFile(BrowserFile); TStream *Stream2; Stream2 = SQLComponents->SQLClientDataSet->CreateBlobStream(SQLComponents->SQLClientDataSet->FieldByName("BLOB"), bmReadWrite); blobField->SaveToStream(Stream2); SQLComponents->SQLClientDataSet->Post(); SQLComponents->SQLClientDataSet->ApplyUpdates(-1); // Disconnect SQLComponents->SQLConnection->Connected = false; SQLComponents->SQLClientDataSet->Active = false; delete[] Buffer; delete Feld; delete SQLComponents;
Das neue ist, daß jetzt mal keine Typenexepction oder ähnliches kommen, sondern scheinbar eine Nachricht der Datenbank (oder der Client Datenmenge)
Und zwar:
"Im Projekt pSaveBlob ist eine Exception der Klasse EDataBaseError" aufgetreten. Meldung:'Datensatz nicht gefunden; Es wurde kein Schlüssel angegeben'"Das kling für mich nach einem (kleinem) Vortschritt!
Jetzt scheint "nur" noch der SQL String nicht ganz richtig zu sein.Den wollt eich dann auch promt in ein INSERT statement umwandeln. Allerdings kenne ich vor dem setzten von "SQLComponents->SQLClientDataSet->CommandText" ja den Datensatzt garnicht, bzw. habe ihn nicht verfügbar. Und connecten ohne CommandText geht nicht. Zudem benutze ich doch den CreateBlobStream Befehl um nicht an Insert Bergänzungen bei der Blobgröße hängen zu bleiben.
komisch das alles....
-
Kann es sein, das in Deiner Tabelle keine Primärschlüsselspalte existiert?
-
Ne!
Die Primärschlusselspalte ist "BLOBX"
-
Damit es hier icht zu langweilig wird, und es auch mal etwas positives zu erzählen gibt. Ichhabe zwar immer nich nicht mein Problem mit dem Speichern gelöst, aber einen recht einfachen Weg gefunden BLOBS aus einer DB in Files zu speichern.
AnsiString SQL1 = "select BLOB from TABLE where BLOBX ="; AnsiString UserName = "Username"; AnsiString Password = "Password"; AnsiString DokuX = Edit1->Text; AnsiString Path = "c:\\temp\\"; AnsiString File ="\0"; AnsiString Query1 = SQL1 + DokuX; if (SQLComponents == NULL) { SQLComponents = new TSQLComponents(NULL); } SQLComponents->SQLConnection->Params->Values["User_Name"] = UserName.c_str(); SQLComponents->SQLConnection->Params->Values["Password"] = Password.c_str() // Blob Auslesen!! SQLComponents->SQLClientDataSet->CommandText = Query1.c_str(); SQLComponents->SQLConnection->Connected = true; SQLComponents->SQLClientDataSet->Active = true; SQLComponents->SQLClientDataSet->SaveToFile(File,dfBinary); SQLComponents->SQLConnection->Connected = false; SQLComponents->SQLClientDataSet->Active = false; delete SQLComponents;
Ich habe dann natürlich gleich die Methode LoadFromFile() ausprobiert. ( keine Ahnung warum ich die nicht früher gefunden hatte ...) Exeptions gab es zwar nicht, Änderungen in der DB aber auch nicht
In der Hilfe stand zusätzlich folgender denkwürdiger Satzt zu:
void __fastcall LoadFromFile(const AnsiString FileName = "");"Hinweis: Die in FileName angegebene Datei muß Daten enthalten, die zuvor durch einen Aufruf der Datenmengenmethode SaveToFile gespeichert wurden"
Toll!
Heißt das, daß ich mit der Funktion nur Files in die DB schreiben darf die da eigentlich schon drinne liegen?? Wäre ja super ...... *mit dem kopf vor die wand schlag*
-
Dein Problem ist also immer noch die Save-Funktion. Hm. Irgendwie ist das da SELECT-Statement noch nicht das richtige. Leider habe ich keine Zeit mich so richtig damit zu beschäftigen. Vielleich ist ja hier noch jemand anderes, der sich damit auskennt.
-
Ich glaube ich werde es jetzt einmal streng nach "Vorschrift" aus dem Entwickler Forum probieren:
void __fastcall TForm1::SaveImageBtnClick(TObject *Sender) { if (OpenPictureDlg->Execute() == false) return; Table->Active = true; Table->Append(); Table->FieldByName("Name")->AsString = ExtractFileName(OpenPictureDlg->FileName); TBlobField* blobField = dynamic_cast <TBlobField*> (Table->FieldByName("PICTURE")); if (blobField == NULL) return; blobField->LoadFromFile(OpenPictureDlg->FileName); Table->Post(); }
Allerdings weiß ich nicht was "Table" für ein Objekt sein soll
Was könnte das sein?
-
Clip schrieb:
Allerdings weiß ich nicht was "Table" für ein Objekt sein soll
Was könnte das sein?Hast Du schon geklärt, ob Dein Problem überhaupt mit dem Blob zusammenhängt?
Versuch doch erstmal, irgend etwas anderes als ein Blob abzuspeichern ... geht das?
-
Ja, das geht völlig Problemlos.
Prügel mich gerade mit SQLTable und SQLQuery. Sah erst alles ganz toll aus.
Dann habe ich bemerkt, dass CanModify von SQLTable immer auf false steht......Ich glaub ich geh wieder mir Papierflugzeugen spielen oder so...
Es muss doch eine Möglichkeit geben Blobs mit dbExpress zu speichern!
Ich werds weiter probieren!
-
Soooooooo
also Blobs aus der DB anzeigen:
AnsiString SQL1 = "select BLOB from TABLE where BLOBX ="; AnsiString SQL2 = "select * from BLOBINFO where BLOBX ="; AnsiString UserName = "username"; AnsiString Password = "passwort"; AnsiString DokuX = Edit1->Text; AnsiString Path = "c:\\temp\\"; AnsiString File ="\0"; AnsiString Query1 = SQL1 + DokuX; if (SQLComponents == NULL) { SQLComponents = new TSQLComponents(NULL); } // Username & Passwort setzten SQLComponents->SQLConnection->Params->Values["User_Name"] = UserName.c_str(); SQLComponents->SQLConnection->Params->Values["Password"] = Password.c_str(); // DateiINfos Auslesen!! SQLComponents->SQLClientDataSet->CommandText = Query2.c_str(); SQLComponents->SQLConnection->Connected = true; SQLComponents->SQLClientDataSet->Active = true; File = SQLComponents->SQLClientDataSet->FieldByName("DATEINAME")->AsString; File = Path + File; SQLComponents->SQLConnection->Connected = false; SQLComponents->SQLClientDataSet->Active = false; // Connecten SQLComponents->SQLClientDataSet->CommandText = Query1.c_str(); SQLComponents->SQLConnection->Connected = true; SQLComponents->SQLClientDataSet->Active = true; // Blob wird ausgelesen TBlobField* blobField = dynamic_cast <TBlobField*> (SQLComponents->SQLClientDataSet->FieldByName("BLOB")); if (blobField == NULL) return; blobField->SaveToFile(File); // disconnect SQLComponents->SQLConnection->Connected = false; SQLComponents->SQLClientDataSet->Active = false; // File Anzeigen WideString WFile; WFile = WideString(File); CppWebBrowser1->Navigate(WFile, NULL, NULL, NULL, NULL); delete SQLComponents;
Blobs in die DB schreiben:
AnsiString SQL1 = "select * from TABLE where BLOBX ="; AnsiString DokuX = Edit1->Text; const AnsiString BrowserFile = "c:\\temp\\test.pdf"; AnsiString Query1 = SQL1 + DokuX; AnsiString Query2 = SQL2 + DokuX; AnsiString UserName = "username"; AnsiString Password = "passwort"; // Hilfsvariablen für Locate() Variant SearchKey = DokuX; TLocateOptions Opts; //Klasse mit benötigten SQL Komponenten if (SQLComponents == NULL) { SQLComponents = new TSQLComponents(NULL); } // Username & Passwort setzten SQLComponents->SQLConnection->Params->Values["User_Name"] = UserName.c_str(); SQLComponents->SQLConnection->Params->Values["Password"] = Password.c_str(); // Query setzten SQLComponents->SQLClientDataSet->CommandText = Query1.c_str(); // connecten SQLComponents->SQLConnection->Connected = true; SQLComponents->SQLClientDataSet->Active = true; // Datensatzt wird ausgewählt Opts.Clear(); Opts << loCaseInsensitive; SQLComponents->SQLClientDataSet->Locate("BLOBX", SearchKey, Opts); // Edit Modus SQLComponents->SQLClientDataSet->Edit(); // Blob wird in den selektierten Datensatzt copiert. TBlobField* blobField = dynamic_cast <TBlobField*> (SQLComponents->SQLClientDataSet->FieldByName("BLOB")); if (blobField == NULL) return; blobField->LoadFromFile(BrowserFile); // Änderungen werden an die DB übertragen SQLComponents->SQLClientDataSet->ApplyUpdates(-1); // disonnect SQLComponents->SQLConnection->Connected = false; SQLComponents->SQLClientDataSet->Active = false; delete SQLComponents;
@admins, evtl. ist das in gekürzter Form ja was für die die FAQs?
-
Äääh ... und was war letztlich das Problem?
-
Zum laden von Daten reicht scheinbar eine Select Anweisung im CommandText um auf ein bestimmtes Datenfeld zuzugrifen. Dies reicht aber nicht wenn etwas gespeichert werden soll. Daher muss nocheinmal der Datensatz ausgewählt werden.
Variant SearchKey = DokuX; TLocateOptions Opts; Opts << loCaseInsensitive; SQLComponents->SQLClientDataSet->Locate("BLOBX", SearchKey, Opts);
Das ist eigentlich alles.
und Vielen Dank für Deine Hilfe noch!!!!!
-
Soviel Aufwand für eine Funktionalität, von deren Anwendung üblicherweise abgeraten wird.
Wenn du das in der FAQ sehen möchtest solltest du aber auch noch den Code deiner SQLComponents-Klasse dazupacken, damit man das 1:1 nachvollziehen kann.
-
Soviel Aufwand für eine Funktionalität, von deren Anwendung üblicherweise abgeraten wird
Warum denn?
Die spezielle Umsetzung die ich jetzt verwendet habe, oder Blobs generell?
-
Generell, weil BLOBs die Datenbank sinnlos aufblähen. Dateien gehören in's Dateisystem, in die DB gehören Links auf die Dateien.
-
Generell stimme ich Dir da zu. Allerdings ist es manchmal notwendig Dateien zu schützen. Und steht genug Datenbanlplatz zur Verfügung ist es halt ein guter weg dies zu tun wenn man sich zusätzlichen administrativen Aufwand sparen will.
Ich werde die Tage die Einstellungen der verwendeten SQL Komponenten zusammenfassen und den Code noch Exeptionsave machen. Danach poste ich dann alles für die FAQs (ich hätte mich gefreut wenns das schon gegeben hätte, daher wirds sicher noch andere geben. Schaden kann es nicht denke ich).
-
Ich weiß das Thema ist schon ziemlich alt, aber ich muss jetzt auch Dateien in eine Datenbank speichern und wieder auslesen und finde einfach nichts brauchbares im Internet, deswegen wollt ich wissen ob es hier (oder woanders) was neues gibt.
So long.