Announcement

Collapse
No announcement yet.

ADOTable erkennt Blob-Feld nicht

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

  • ADOTable erkennt Blob-Feld nicht

    Hallo zusammen!

    Ich bin nun schon seit Tage an einem Problem und finde leider keine Lösung. Ich hoffe, dass von Euch jemand helfen kann.

    Ich habe ein MySQL-Tabelle der Form:

    Code:
    CREATE TABLE  `TableTest` (
      `id` int(10) unsigned NOT NULL auto_increment,
      `Feld1` int(10) unsigned default NULL,
      `Feld2` int(10) unsigned default NULL,
      `Daten` blob NOT NULL,
      PRIMARY KEY  (`id`)
    ) TYPE=MyISAM;
    Auf diese Tabelle möchte ich mit den ADO-Komponenten zugreifen. Das Problem dabei ist, dass TADOTable das Blob-Feld nicht erkennt:

    Table.FieldByName('Daten').IsBlob liefert immer false.

    Ich möchte eigentlich nur einen Stream in das Blob-Feld speichern. Scheinbar gibt es dafür n+1 Möglichkeiten (ADOTable, Recordsets, ADOQuery etc.). Ich habe wirklich alle im Netz gefunden Lösungsansätze probiert und nicht einer funktioniert.

    Hier der Lösungsansatz, der mit am logischsten erscheint: es wird an eine Prozedur "SaveData" ein Pointer auf einen MemoryStream übergeben. Die Methode soll nun den Inhalt dieses Streams in die Tabelle "TableTest" ins Feld "Daten" speichern --- so der Plan...

    Beim der Zeile

    TBlobField(Table.Fields.FieldByName('Daten')).Load FromStream(TMemoryStream(Data^));

    steigt mir das Programm mit der Exception "ungültige Typumwandlung" aus.

    Wäre super, wenn einer von Euch helfen könnte!

    Danke im Voraus!

    Code:
    procedure TALTForm.Button1Click(Sender: TObject);
    var
      Data : TMemoryStream;
      Texxt : String;
    begin
      Data := TMemoryStream.Create;
      Data.Clear;
    
      Texxt := 'Hallo Welt!';
      Data.Write(Texxt,SizeOf(Texxt));
      Data.Position := 0;
    
      SaveData(@Data);
      
      Data.Free;
    end;
    
    procedure SaveData(Data : Pointer);
    var
      Table: TADOTable;
    begin
        Table := TADOTable.Create(nil);
        Table.Connection := Database.DB;
        Table.TableName := 'TableTest';
        Table.Filtered := false;
        Table.Filter := 'idDaten=4';
        Table.Filtered := true;
        Table.Open;
        Table.First;
    
        Table.Edit;
        
        TMemoryStream(Data^).Seek(0, soFromBeginning);
    
        TBlobField(Table.Fields.FieldByName('Daten')).LoadFromStream(TMemoryStream(Data^));
        
        Table.Post;
        Table.Free;
    end;

  • #2
    Hi,

    ich habe das Problem "Datei in blob speichern" folgendermassen erlegt:

    var
    FaxStream :TFileStream;
    DBSTream :TStream;
    begin
    FaxStream := TFileStream.Create(Filename + '.tif', fmOpenRead);
    DBSTream := CreateBlobStream(myADODataset.FieldByName('Fax'), bmWrite);
    DBSTream.CopyFrom(FaxStream, 0);
    DBSTream.free;
    FaxStream.Free;
    end;

    Vielleicht hilft dir das weiter.

    Grüße

    Julia

    Comment


    • #3
      Hi,

      Hab das eben mal ausprobiert, allerdings unter ORACLE mit einem LONG Feld.
      Da hat es einwandfrei funktioniert.

      Allerdings hast du zumindest ein Fehler in deinem CODE

      Code:
        Texxt := 'Hallo Welt!';
        Data.Write(Texxt,SizeOf(Texxt));
      Die Funktion SizeOf gibt bei einem String immer 4 zurück, da Strings in Delphi intern als Pointer verwaltet werden, und diese 4 Byte groß sind.

      Demnach schreibt die Zeile
      Code:
      Data.Write(Texxt,SizeOf(Texxt));
      schonmal nicht das erwartete in den Stream.

      Da das ganze auch noch ein MemoryStream ist, wird dort wohl irgend ein Teil einer Speicheradresse oder so abgespeichert...

      Wenn du nur Text in das Feld schreiben willst, dann versuch doch mal das:

      Code:
      ...
      Data:= TStringStream.Create('Hallo Welt!');
      ...
      SaveData(@Data);
      ...
      und in SaveData änderst du alles auf TStream ab, anstelle von TMemoryStream. Das sollte auch gehen.



      Gruß

      Stefan Laut

      Comment


      • #4
        Hi habe inzwischen die Lösung gefunden!

        Stefan hat Recht, das mit dem SizeOf war natürlich falsch.

        Der Bereich des Datenfüllens lautet

        Code:
        Stream.Clear;
        Stream.Write('Hallo Pest',10);
        SaveData(@LIVStream);
        Die Routine für das Handling mit der DB sieht folgendermaßen aus:

        Code:
        procedure TMessung.SaveData(Data : Pointer);
        var
           ....
        begin
          TMemoryStream(Data^).Seek(0, soFromBeginning);
        
          Tabelle := '`db2`.`tab1`';
        
          Database.InsertQuery.SQL.Clear;
          Database.InsertQuery.SQL.Add('INSERT INTO '+Tabelle+' (IdMessung, daten) VALUES ');
          Database.InsertQuery.SQL.Add('(:IdMessung, :Daten)');
        
          Database.InsertQuery.Parameters.ParamByName('IdMessung').Value := GetID;
          Database.InsertQuery.Parameters.ParamByName('Daten').LoadFromStream(TMemoryStream(Data^),ftBlob);
        
          Database.InsertQuery.ExecSQL;
        end;
        Danke für Eure Mithilfe!

        Comment

        Working...
        X