Announcement

Collapse
No announcement yet.

SQLServer - (TBlobField*)->SaveToFile()

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • SQLServer - (TBlobField*)->SaveToFile()

    Hallo,

    ich habe das Problem, dass der korrekt in der DB gespeicherte Inhalt eines TBlobField's (in der DB ist der Spaltentyp "text") nicht in voller Länge mit(TBlobField*)->SaveToFile() als Datei gespeichert werden kann. Die Datei ist immer 32KB groß. Auch dann, wenn der Inhalt größer ist!

    Hilfe, Joachim

  • #2
    Hallo,

    über welchen Weg (BDE, ODBC, ADO) wird auch welche SQL Server-Version zugegriffen? Im Fall von ODBC hängt es vom Treiber ab, einige verwenden einen Konfigurationseintrag für die maximale BLOb-Größe.

    Bei dem von Microsoft offziell vorgesehenen Weg (Stream-Objekt von ADO) gibt es keine Beschränkungen. Das folgende Beispiel demonstriert den Einsatz:
    <pre>
    { Ausgewählte Datei via Stream-Objekt von ADO in der SQL Server 7-Datenbank
    ablegen und gleich wieder aus der Datenbank auslesen und unter einem
    anderen Dateinamen abspeichern. }

    procedure TForm1.ToolButtonBLOBClick(Sender: TObject);
    resourcestring
    RS_SQL = 'SELECT ID, FileContents FROM StreamBLOBDemo WHERE 1 = 0';
    SELECT = 'SELECT ID, FileContents FROM StreamBLOBDemo WHERE ID = ';
    var
    aADOStream : _Stream;
    aRS : _RecordSet;
    iID : Integer;
    vSQL : OleVariant;
    begin
    // Step 1: ADO-Stream-Objekt initialisieren
    aADOStream := CoStream.Create;
    aADOStream.Type_ := adTypeBinary;
    aADOStream.Open(EmptyParam, adModeUnknown, adOpenStreamUnspecified, '', '');
    aADOStream.LoadFromFile(FFileName);
    MemoLog.Lines.Add(FFileName + ' in ADO-Stream-Objekt geladen.');
    // Step 2: ADO-Recordset-Objekt initialisieren
    aRS := CoRecordset.Create;
    aRS.CursorLocation := adUseClient;
    vSQL := RS_SQL;
    aRS.Open(vSQL, ADOConnection1.ConnectionObject,
    adOpenStatic, adLockOptimistic, adCmdText);
    MemoLog.Lines.Add('....ADO-Recordset-Objekt initialisiert.');
    // Step 3: Neuen Datensatzpuffer anfordern
    aRS.AddNew(EmptyParam, EmptyParam);
    iID := StrToInt(EditID.Text);
    MemoLog.Lines.Add('....Neuen Datensatzpuffer angefordert.');
    // Step 4: Werte zuweisen, BLOb aus Stream-Objekt zuordnen
    aRS.Fields.Item['ID'].Value := iID;
    aRS.Fields.Item['FileContents'].Value := aADOStream.Read(adReadAll);
    MemoLog.Lines.Add('....BLOb aus Stream-Objekt zugeordnet.');
    // Step 5: Datensatz speichern
    aRS.Update(EmptyParam, EmptyParam);
    aRS.Close;
    aADOStream.Close;
    aRS := nil;
    aADOStream := nil;
    MemoLog.Lines.Add('...Datensatz gespeichert.');
    // Step 6: Datensatz zur Kontrolle neu einlesen
    aRS := CoRecordset.Create;
    vSQL := SELECT + IntToStr(iID);
    aRS.Open(vSQL, ADOConnection1.ConnectionObject,
    adOpenForwardOnly, adLockReadOnly, adCmdText);
    MemoLog.Lines.Add('...Datensatz zur Kontrolle neu eingelesen.');
    // BLOb-Inhalt über Stream-Objekt auslesen und als Datei speichern
    aADOStream := CoStream.Create;
    aADOStream.Type_ := adTypeBinary;
    aADOStream.Open(EmptyParam, adModeUnknown, adOpenStreamUnspecified, '', '');
    aADOStream.Write(aRS.Fields.Item['FileContents'].Value);
    aADOStream.SaveToFile(FSaveFileName, adSaveCreateOverWrite);
    MemoLog.Lines.Add(FSaveFileName + ' gespeichert');
    aADOStream.Close;
    aRS.Close;
    Inc(iID);
    EditID.Text := IntToStr(iID);
    end;
    </pre&gt

    Comment


    • #3
      Hallo,

      vielen Dank für die promte Antwort!
      Ich greife mit der Komponente TQuery i.V. mit der BDE und dem ODBC-Treiber auf einen SQLServer7 zu. Hierbei tritt der beschriebene Effekt auf.
      Dein Beispiel kann ich nicht ohne weiteres nachvollziehen. Ich setze den cBuilder5 Prof. ein und habe hier keine ADO-Objekte zur Verfügung. Ich hoffe auf eine Lösung mit den von mir eingesetzten Komponenten.
      Davon mal abgesehen ist ADO ein interessantes Thema, mit dem ich mich wohl zukünftig mal beschäftigen werde (muss).

      Grüße
      Joachi

      Comment


      • #4
        Hallo,

        ab dem Microsoft SQL Server 7 ist ADO die von Microsoft vorgesehene Zugriffsart, die alte DBLib-Schnittstelle wurde entsorgt (d.h. bleibt auf dem Stand der Version 6.5). Ich habe schon mehrfach von den Beschränkungen des ODBC-Treibers gehört/gelesen, wenn ich mich richtig erinnere, war dabei die Standard-Antwort von Microsoft immer "Wechseln Sie zu ADO". Da ich selbst den ODBC-Treiber nicht verwende, musste ich nicht nach einem Workaround für dieses Problem suchen.

        Mein ADO-Beispiel greift auf die originalen ADO-Objekte von Microsoft zurück, die immer dann vorhanden sind, wenn MDAC auf dem Rechner installiert ist. Über <i>Projekt | Typbibliothek importieren</i> kann man diese Objekte einbinden. Der Bezug auf <i>ADOConnection1.ConnectionObject</i> kann durch den direkten Zugriff auf das Connection-Objekt ersetzt werden, die ADO Express-Komponenten von Borland werden nicht benötigt

        Comment


        • #5
          Hallo,<br>
          <br>
          langsam (aber stetig) gehts voran...<br>
          Ich habe die Typbibliothek (ADO 2.6) importiert. Beim compilieren bekam ich allerdings eine Fehlermeldung => in der Zeile <br>
          (OnWillExecute)(this, TVariant(params[0]), (Adodb_tlb::CursorTypeEnum*)(int*)TVariant(params[1]), (Adodb_tlb::LockTypeEnum*)(int*)TVariant(params[2]), TVariant(params[3]), (Adodb_tlb::EventStatusEnum*)(int*)TVariant(params[4]), (Adodb_tlb::_Command*)(LPDISPATCH)TVariant(params[5]), (Adodb_tlb::_Recordset*)(LPDISPATCH)TVariant(param s[6]), (Adodb_tlb::_Connection*)(LPDISPATCH)TVariant(para ms[7]));<br>
          wird der Fehler <br>
          [C++ Fehler] ADODB_OCX.cpp(131): E2034 Konvertierung von 'TVariant' nach 'long *' nicht möglich<br>
          angezeigt. Nachdem ich die Definition des Parameters dieser und einer weiteren Funktion von long* auf long geändert habe, wird fehlerfrei compiliert (ob das so richtig ist?).<br>
          Jetzt stehen mir die neuen Komponenten zur Verfügung. Da ich von Pascal keine Anhnung habe, stehe ich jetzt vor dem nächsten Problem. Dein Beispiel nach C++ bzw. für den cBuilder zu portieren ist mir bis jetzt nicht gelungen. Gibt es Beispiele für die Anwendung von ADO (nicht ADOExpress!) auch für den cBuilder (Internet, Bücher, Zeitschriften, dieses Forum,...)?

          Tschau, Joachi

          Comment


          • #6
            Hallo,

            äh - das ist genau der Grund für den Erfolg von Delphi ;-)<br>
            (im Gegensatz zum firmenübergreifenen C/C++-Standard kann Borland das COM-Prinzip bei Object Pascal in den Compiler und in die Sprache einbauen, und hat das ab Delphi 3 auch so gemacht).

            Ich würde im MSDN (Microsoft Developer Network) suchen, denn dort gibt es ADO-Beispiele sowohl für Visual Basic (diese Beispiele können mit Delphi einfach nachgebaut werden) als auch für C++

            Comment

            Working...
            X