I have a TComponent class derivative like below, trying to save to a clientdataset blob field: (Copied from internet, due credits)
type
TSaveComponent = class(TComponent)
private
FFileName: string;
public
constructor Create(AFileName:string);
destructor Destroy;
procedure ReadFromBlobField1(AField: TField);
procedure SaveToBlobField1(AField: TField);
end;
...
constructor TSaveComponent.Create(AFileName: string);
begin
Name := Copy(Self.ClassName, 2, 99);
FFileName := AFileName; //-- disabled file saving for now
end;
procedure TSaveComponent.ReadFromBlobField1(AField: TField);
var
Stream: TStream;
i: integer;
begin
try
Stream := TClientDataSet(AField.DataSet).CreateBlobStream(AField, bmRead);
try
{delete the all child components}
for i := Self.ComponentCount - 1 downto 0 do
Self.Components[i].Free;
Stream.ReadComponent(Self); //--ERROR here: Stream read error.
finally
Stream.Free;
end;
except
on EFOpenError do {nothing};
end;
end;
procedure TSaveComponent.SaveToBlobField1(AField: TField);
var
Stream: TStream;
begin
Stream := TClientDataSet(AField.DataSet).CreateBlobStream(AField,bmWrite);
try
Stream.WriteComponent( Self);
finally
Stream.Free;
end;
end;
Firebird table is ...
CREATE TABLE APPOBJECTS
(
FORMDM_NAME varchar(31),
OBJ_NAME varchar(40),
OBJECT blob sub_type 1,
CONSTRAINT UNQ_NAME UNIQUE (OBJ_NAME)
);
Writing to db ...
with dmMain.ClientDataSet2 do
begin
if Locate('OBJ_NAME',GlobalSetting.Name,[]) then
Edit
else
Append;
FieldByName('OBJ_NAME').AsString := GlobalSetting.Name;
end;
GlobalSetting.SaveToBlobField1(dmMain.ClientDataSet2.FieldByName('OBJECT'));
dmMain.ClientDataSet2.Post;
dmMain.ClientDataSet2.ApplyUpdates(0);
(Globalsetting is TSaveComponent.)
Reading from db ...
with dmMain.ClientDataSet2 do
begin
if Locate('OBJ_NAME',GlobalSetting.Name,[]) then
begin
GlobalSetting.ReadFromBlobField1(dmMain.ClientDataSet2.FieldByName('OBJECT'));
end;
end;
PROBLEM: "Stream read error" in Stream.ReadComponent(self) line, always. How to solve this, please?
I can confirm saving the component works. I inspected the table and see the published fields in GlobalSetting, I'm just not sure if it is the correct format. (I can show the hex representation if needed)
EDIT:
The whole solution works with IBX components;
With DBExpress/Clientdataset components, reading the stream from the blob field always results in 'Stream read error.'
The Firebird table DDL should have been defined as follows (note sub_type 0, not 1 as originally defined):
What a .... been ignoring it all the while.
Reference: http://www.firebirdfaq.org/faq165/