Entwickler-Ecke
Datenbanken - SaveToStream in Firebird Datenbank
mexx - Mi 24.01.07 12:23
Titel: SaveToStream in Firebird Datenbank
Hallo,
ich möchte einen Report als Stream in ein Blob-Feld speichern. Dafür gibt es ja die Procedure SaveToStream. Leider weis ich nicht, wie ich sie anwenden kann, dass das Blob gespeichert wird und wie ich dem Speichern noch andere Parameter mitgebe, wie zum Beispiel die Primär-Schlüssel der Tabelle.
Hier mal meine Anfänge.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| function TFastRepotModul.MainDesignerSaveReport(Report: TfrxReport; SaveAs: Boolean): Boolean; var BlobStream: TSTream; begin BlobStream := TMemoryStream.Create; MainFstRpt.SaveToStream(BlobStream,false,false);
BlobStream.Free; end; |
Schreibt einfach auf, was euch einfällt oder Links, wo ich mir was anlesen kann.
Thx, mexx
mexx - Mi 24.01.07 16:32
Ich verwende Delphi7, FastReport4.0 und InfoPower Komponenten(Database, Query,...). Ein Wechsel der Kompontenten kommt ist nicht möglich. Ich werde mir die Source mal vornehmen. Vielen Dank! Was andere nicht davon abhalten sollte, Ihr Wissen preis zu geben.
hansa - Mi 24.01.07 17:35
Guck mal hier :
http://www.delphi-tutorials.de Das ist Lemmy's Seite. Da ist ein Tutorial vorhanden : "Blobs in IB/FB" oder so ähnlich. Les dir das mal durch.
mexx - Mo 29.01.07 12:54
Die Links haben mir nicht geholfen. Das Tutorial kann man kaum als ein solches Bezeichnen! 2 Seiten und mehr Geschichte als erklärter Quellcode. Meine Frage bleibt also noch offen. Wie Speicher und Lade ich Blobs?
mkinzler - Mo 29.01.07 13:17
Schau dir mal die TBlobStream-Klasse an.
UGrohne - Mo 29.01.07 13:20
Ich habe mal nach den InfoPower-Komponenten gesucht. Seltsamerweise finde ich dort keine Datenbankzugriffskomponenten. Bist Du sicher, dass dort welche dabei sind? Und wenn nicht, welche Komponenten verwendest Du für den Zugriff auf Firebird? BDE? ZEOS? IBX?
mexx - Mo 29.01.07 13:32
Also die Komponenten sind von Wall2Wall, wo auch die FirstClass-Komponenten her kommen. Die Verbindung erfolgt über TDatabase mit Session. Normale TDatasource. Nur die Query ist eine TwwQuery. Sie ist nicht besonders anders als die normale TQuery, sie besitzt nur mehr funktionen. Mir geht es primär um das Laden und Speichern von Blobs in die Firebird.
Die FastReport-Komponenten kennt wohl keiner? Mein Ziel ist es FastReports zu speichern, mal als Template mal als Child. Und auch wieder zu laden.
Moderiert von
UGrohne: Beiträge zusammengefasst.
UGrohne - Mo 29.01.07 14:04
Wenn Du sagst, Du verwendest TDatabase und TQuery, dann frage ich mich, warum Dir beide Tutorials nichts gebracht haben, denn genau diese Vorgehen sollten dort auch funktionieren. Was hast Du denn geschrieben, was nicht funktioniert hat? Und worin äußerte es sich, dass es nicht funktioniert hat?
FastReport kennen sicher ein paar hier, aber die haben damit ja überhaupt nichts zu tun. Genauso wie InfoPower.
mexx - Mo 29.01.07 14:14
Ich befürchte fast, wir reden an einander vorbei.
Ich habe eine Firebird-Tabelle, mit einen Feld "ID","Bezeichnung","Blob". In das Blob möchte ich nun meinen Report speichern und laden. Aber wie, wenn ich einen bestimmte ID haben möchte?
Um es noch genauer zu machen. Ich möchte nun diesen Report als Template speichern. Da ich aber weder weis, wie ich ÜBERHAUPT ein Blob speicher, noch wie ich ein Template als Blob speicher und lade, weis ich nicht wo ich anfangen soll.
Ich habe NULL ahnung vom umgang mit Blob. Überall wird zwar erklärt wie es geht, aber zum einem immer nur anhand einer Datei, wo das Kriterium einer Tabellen-ID nicht erklärt wird, oder es wird nur gezeigt, wie ich einen Stream erzeuge, aber nicht abspeicher. Die Hilfe für die FastReport ist sehr mangelhaft.
UGrohne - Mo 29.01.07 14:21
Wie bereits gesagt, FastReport hat damit AFAIK nichts zu tun. Das Einzige, was Du brauchst ist Quelltext, wie man eine Datei in ein Blob-Feld speichert und wieder daraus lädt. Oder irre ich mich da?
Wenn nicht, dann sollten Dir die beiden genannten Quellen eigentlich reichen. Was meinst Du aber mit der bestimmte ID? Die musst Du doch nur setzen, wenn Du die brauchst. Normalerweise arbeitet man für die IDs mit Generatoren. Oder willst Du eine Baumstruktur abbilden? Dann brauchst Du ein weiteres Feld, das die ID des Parents enthält.
Irgendwie blick ich langsam nicht mehr, was Du eigentlich genau machen willst, für Deine eigentliche Frage sollte inzwischen genug hier stehen.
mexx - Mo 29.01.07 14:24
Mir ist schon klar, dass ich die ID generieren lassen kann. Aber wie speicher ich den Stream zum Beispiel bei der ID 4 ab? Einen Stream zu erzeugen ist kein Problem und Ihn zu speichern, aber wie mache ich das bei der ID 4?
mkinzler - Mo 29.01.07 14:28
Hast du die Tabelle um ein Blob-feld erweitert?
mexx - Mo 29.01.07 14:29
Ja
mkinzler - Mo 29.01.07 14:31
Dann verstehe ich deine Frage nicht ganz.
mexx - Mo 29.01.07 14:35
Ich habe einen Report. Man könnte diesen Report als Datei abspeichern. Statt Ihn aber als Datei abzuspeichern, möchte ich den Report, in eine Firebird-Datenbank speichern. In eine dafür vorgesehene Tabelle mit einem Primärschlüssel. Bei den Report handelt es sich um einen mit FastReport 4.0 erstellten Report. Die einzige Information, welche ich über das Speichern von solchen Reports in Datenbanken habe, ist die mangelnde Hilfe der FastReport-Komponeten, welche mir lediglich sagt, dass es geht, aber leider nicht wie.
Wie speicher ich einen Report in einer Datenbank?
Edit:
Delphi-Quelltext
1: 2: 3: 4: 5:
| Blobstream := TStream.Create; BlobStream.Position := 0; MainFstRpt.SaveToStream(BlobStream); BlobStream.Free; |
Bei der MainFstRpt handelt es sich um die Non-VCL von FastReport. Nun habe ich den erstellten Report als Stream und möcte diesen nun in der Tabelle abspeichern. Aber unter einen Bestimmten schlüssel der Tabelle, welchen ich auch kenne. Sagen wir mal 4! Wie speicher ich nun diesen Stream in die Tabelle?
mkinzler - Mo 29.01.07 14:41
SQL-Anweisung
1:
| insert into <Tabelle> (<ID>, <Blobfeld>) values (:ID, :Blob); |
Delphi-Quelltext
1:
| query.ParamByName('Blob').LoadFromStream( ... ); |
UGrohne - Mo 29.01.07 15:13
Nimm doch einfach den Quellcode aus meinem ersten Link, lass das INSERT weg und mach den Select auf den Datensatz mit der ID. Wir können Dir hier keinen Quellcode für Copy & Paste geben, Du musst schon selbst auch etwas machen.
mexx - Mo 29.01.07 15:24
Das will ich ja auch nicht. Hilfe zur Selbsthilfe bringt viel mehr. Der einfache Satz "Mexx, behandel ein Blob wie ein Value eines Insert bzw. eines Updates." hätte meine Fragen beantwortet. Dann hätte ich gewusst, dass ich den Stream zu zuweisen muss und über eine einfach SQL abschicke. Es ist erschreckend, aber so einfach die Lösung ist, sie steht nirgenswo geschrieben.
Aber ein Hauptproblem bleibt bestehen. Reports als Template in Blob speichern. Du hast von Usern gesprochen, die mit FastReport arbeiten. Kannst Du mir Ihren Namen nenne. Ein paar theretische Fragen würde ich klären wollen.
UGrohne - Mo 29.01.07 15:55
Im Moment kenne ich keine Namen, tut mir leid. Aber ich verstehe nicht, wie Du mit Hilfe meines Links nicht auf genau das Ergebnis kommen konntest, denn schließlich hab ich dort auch einen Datensatz selektiert und dann ein Blob eingefügt. Deswegen hab ich einfach nicht verstanden, worauf Du hinaus willst.
mexx - Mo 29.01.07 16:20
In Deinen Tut finde ich keine Zeile, in der das ersichtlich wird.
UGrohne - Mo 29.01.07 16:33
mexx hat folgendes geschrieben: |
In Deinen Tut finde ich keine Zeile, in der das ersichtlich wird. |
Dann schau Dir mal Zeile 5 im ersten Code an.
mexx - Mo 29.01.07 16:40
Ja, Du setzt den Zeiger deiner Datenmenge auf einen bestimmten Datensatz. Jetzt im Nachgang wirds ersichtlich, aber ich wusste einfach nichts damit anzufangen. Ich bin einfach nicht auf die Idee gekommen, dass es wie eine Variable zu handhaben ist.
mexx - Di 30.01.07 11:25
Ich muss mal weiter fragen. Ich verwende zum Laden des Reports diesen Code und erhalte eine Zugriffsverletzung. Was mache ich falsch?
Delphi-Quelltext
1: 2: 3: 4: 5:
| BlobStream := TMemoryStream.Create; BlobStream.Position := 0; BlobStream := TBlobStream(FieldByName('REPORT')); MainFstRpt.LoadFromStream(BlobStream); BlobStream.Free; |
mexx - Di 30.01.07 11:29
Okay, ich habs gefunden.
Delphi-Quelltext
1: 2: 3: 4: 5:
| BlobStream := TMemoryStream.Create; BlobStream.Position := 0; BlobStream := CreateBlobStream(FieldByName('REPORT'),bmReadWrite); MainFstRpt.LoadFromStream(BlobStream); BlobStream.Free; |
Aber nun erhalte ich die Meldung, dass die Datenmenge nicht im Editiermodus sei, aber was spielt das für eine Rolle, wenn ich nur lesen will?
mexx - Di 30.01.07 11:31
Ich bin doch echt vom blöden und blinden Fisch bespuckt. Logo, wenn ich TBlobStreamMode auf bmReadWrite setzte und das auf der Datenmenge liegt, erhalte ich die Meldung. TBlobStreamMode auf bmRead gesetzt und schon geht es.
HelgeLange - Do 01.02.07 23:45
ok, da sich keiner direkt dazu geäussert hat und ich leider auch nun nicht sehe, ob das Problem schon gelöst ist oder nur teilweise, schreib ich einfach mal was dazu...
ich weiss nicht, inwieweit du verstanden hast, wie Firebird/Interbase Blobs verwaltet, deswegen fang ich da mal kurz an.. dann wird das ganze nachher nämlich auch logisch.
Einfach ausgedrückt gibt es einen Bereich in der DB, wo die ganzen blobs gespeichert werden (da sie nicht in der Tabelle selbst gespeichert werden können). Jeder Blob erhált dazu einen Descriptor, die BlobID. Die erhälst Du beim Schreiben des Blobs bzw. wenn Du eine Abfrage auf eine Tabelle mit blob machst, kriegst Du ja eigentlich nicht den Blob, sondern erstmal nur die BlobID. Mit dieser kannst Du dir dann den blob abholen. Die meisten wissen es sicherlich nicht, da das ja die Komponenten für sie alles erledigen ;)
Zur Vorgehensweise beim Speichern eines Blobs : Erstmal packst Du alles in einen BlobStream, hier ein Beispiel aus meinem CodeBase, der seit Jahren so läuft und funktioniert :
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| procedure WriteBlob(var BlobID: TISC_QUAD; Stream: TMemoryStream; DB: TFIBDatabase; TA: TFIBTransaction; StreamPos: Integer = 0); var BlobStream : TFIBBlobStream; begin If not Assigned(Stream) Then Exit;
BlobStream := TFIBBlobStream.Create; BlobStream.Database := DB; BlobStream.Transaction := TA; BlobStream.Mode := bmReadWrite; BlobStream.BlobID := BlobID; Stream.Position := StreamPos; BlobStream.LoadFromStream(Stream); Stream.Position := StreamPos; BlobStream.Finalize; BlobID := BlobStream.BlobID; BlobStream.Free; end; |
Dies ist natürlich eine Generelle Schreibmethode, kann also neue Blobs anlegen sowie vorhandene updaten. In Zeile 10 setze ich die BlobID dazu vor dem Schreiben, dadurch wird ein vorhandener Blob ersetzt, sofern es eine gültige BlobID ist. Du erhälst die BlobID deines Datensatzes bei der Abfrage, steckst sie zusammen mit den anderen Infos in diese Funktion und danach schreibst du die erhaltene BlobID wieder in die Datenbank mithilfe eines updates.
Schaust Du dir die BlobID vor dem Schreiben des Blobs und danach mal im Debugger an, wirst Du sehen, dass sie recht unterscheidlich aussehen. Das liegt daran, dass der geschriebene Blob erstmal nur vorläufig drin ist, da Du die BlobID noch nicht gespeichert hast und somit der Blob noch nicht vollständig ist.
und hier noch eben das Lesen des Blobs
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| procedure LoadBlob(BlobID: TISC_QUAD; var Stream: TMemoryStream; DB: TFIBDatabase; TA: TFIBTransaction; bCanFreeStream: Boolean = True); var BlobStream : TFIBBlobStream; begin If not Assigned(Stream) Then Stream := TMemoryStream.Create; BlobStream := TFIBBlobStream.Create; BlobStream.Database := DB; BlobStream.Transaction := TA; BlobStream.Mode := bmRead; BlobStream.BlobID := BlobID; BlobStream.SaveToStream(Stream); Stream.Position := 0; If Stream.Size = 0 Then If bCanFreeStream Then FreeAndNil(Stream); BlobStream.Finalize; BlobStream.Free; end; |
So, hoffe das hilft Dir ein bissl, die Blobgeschichte zu verstehen. Wenn Du noch weitere Fragen hast...
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!