Delphi 将对象另存/加载为数据库中的blob

Delphi 将对象另存/加载为数据库中的blob,delphi,Delphi,我的代码怎么了?我试图保存一个对象,然后再次将其加载到数据库中的blob字段中,但什么也没有得到 记录被保存,但我不能说数据是否被正确写入,因为我无法读回数据 以下是对象类型: TMyObject = class Name: string; end; 在这里,我试图保存: procedure TForm1.btnSaveObjectClick(Sender: TObject); var myObject: TmyObject; aMemoryStream: TMemoryStrea

我的代码怎么了?我试图保存一个对象,然后再次将其加载到数据库中的blob字段中,但什么也没有得到

记录被保存,但我不能说数据是否被正确写入,因为我无法读回数据

以下是对象类型:

TMyObject = class
  Name: string;
end;
在这里,我试图保存:

procedure TForm1.btnSaveObjectClick(Sender: TObject);
var
  myObject: TmyObject;
  aMemoryStream: TMemoryStream;
begin
  myObject:= TMyObject.Create;
  myObject.Name:=edtName.Text;
  aMemoryStream:= TMemoryStream.Create;
  aMemoryStream.Write(myObject, myObject.InstanceSize);
  aMemoryStream.Position:=0;

  with TSQLQuery.Create(nil) do
  begin
    DataBase:=Conn;
    SQL.Text:='INSERT INTO testtable (data) VALUES (:data)';
    try
      ParamByName('data').LoadFromStream(aMemoryStream, ftBlob);
      ExecSQL;
      TX.CommitRetaining;
    finally
      aMemoryStream.Free;
      myObject.Free;
      Free;
    end;
  end;
end;
正在尝试重新读取数据备份:

procedure TForm1.btnLoadObjectClick(Sender: TObject);
var
  myObject: TMyObject;
  BlobStream : TStream;
begin
  with TSQLQuery.Create(nil) do
  begin
    DataBase:=Conn;
    SQL.Text:='SELECT data FROM testtable';
    myObject:= TmyObject.Create;
    try
      Open;
      Last;
      BlobStream:= CreateBlobStream(FieldByName('data'), bmread);
      BlobStream.Position:=0;
      BlobStream.Read(myObject, BlobStream.Size);
      ShowMessage('Stored Name: ' +myObject.Name);
    finally
      myObject.Free;
      Free;
    end;
  end;
end;

此外,BlobStream是否应该被释放?

将对象存储到文件、流或blob字段中的正确方法是首先使用其他方法扩展对象,以便将数据从对象字段(对象内部变量)加载并保存到单个内存块中

您可以通过一个接一个地保存字段来实现这一点

如果对象是动态大小的(包含动态数组或字符串),请不要忘记单独存储这些对象的大小,以便在以后加载对象时知道有多少数据属于它们

此外,如果您的对象包含一些其他对象,您也需要它们具有类似的方法来存储和加载其数据


实现在很大程度上取决于对象的类设计。下面是字符串字段的代码示例:

type
  TMyObject = class
  public
    Name: string;
    procedure SaveToStream(AStream: TStream);
    procedure LoadFromStream(AStream: TStream);
  end;

procedure TMyObject.SaveToStream(AStream: TStream);
var
  Len: Integer;
begin
  Len := Length(Name);
  AStream.Write(Len, SizeOf(Len));
  AStream.Write(PChar(Name)^, Len);
end;

procedure TMyObject.LoadFromStream(AStream: TStream);
var 
  Len: Integer;
begin
  AStream.Read(Len, SizeOf(Len));
  SetString(Name, PChar(nil), Len);
  AStream.Read(PChar(Name)^, Len);
end;
这样,就可以使用CreateBlobStream返回的流,只需将myObject保存到blobfield:

BlobField := FieldByName('data') as TBlobField;
Stream := CreateBlobStream(BlobField, bmWrite);
myObject.SaveToStream(Stream);
..或从流中加载:

Stream:= CreateBlobStream(FieldByName('data'), bmread);
myObject.LoadFromStream(Stream);

将对象存储到文件、流或blob字段中的正确方法是,首先使用其他方法扩展对象,以便将对象字段(对象内部变量)中的数据加载并保存到单个内存块中

您可以通过一个接一个地保存字段来实现这一点

如果对象是动态大小的(包含动态数组或字符串),请不要忘记单独存储这些对象的大小,以便在以后加载对象时知道有多少数据属于它们

此外,如果您的对象包含一些其他对象,您也需要它们具有类似的方法来存储和加载其数据


实现在很大程度上取决于对象的类设计。下面是字符串字段的代码示例:

type
  TMyObject = class
  public
    Name: string;
    procedure SaveToStream(AStream: TStream);
    procedure LoadFromStream(AStream: TStream);
  end;

procedure TMyObject.SaveToStream(AStream: TStream);
var
  Len: Integer;
begin
  Len := Length(Name);
  AStream.Write(Len, SizeOf(Len));
  AStream.Write(PChar(Name)^, Len);
end;

procedure TMyObject.LoadFromStream(AStream: TStream);
var 
  Len: Integer;
begin
  AStream.Read(Len, SizeOf(Len));
  SetString(Name, PChar(nil), Len);
  AStream.Read(PChar(Name)^, Len);
end;
这样,就可以使用CreateBlobStream返回的流,只需将myObject保存到blobfield:

BlobField := FieldByName('data') as TBlobField;
Stream := CreateBlobStream(BlobField, bmWrite);
myObject.SaveToStream(Stream);
..或从流中加载:

Stream:= CreateBlobStream(FieldByName('data'), bmread);
myObject.LoadFromStream(Stream);

不能像这样保存对象,因为对象引用只是一个指针。此外,您发布的示例是一个简单的字符串,您可以在数据库中创建一个
char
varchar
列来保存该信息。@KenWhite您介意分享正确的语法吗?我实际上想知道如何保存对象并将其加载到blobfield。选择简单类型是为了不使事情复杂化。字符串长度是可变的,这使得它更加困难,这也是故意的。:-)加载/保存blob字段的数量。对于对象,您需要完全不同的东西。您的任务包括两个步骤,对象反序列化和保存/加载到BLOB字段。我已经说过(还有@TLama),您不能直接将对象存储到BLOB字段,因此没有正确的语法。在此处搜索
[delphi]序列化
。不能保存这样的对象,因为对象引用只是一个指针。此外,您发布的示例是一个简单的字符串,您可以在数据库中创建一个
char
varchar
列来保存该信息。@KenWhite您介意分享正确的语法吗?我实际上想知道如何保存对象并将其加载到blobfield。选择简单类型是为了不使事情复杂化。字符串长度是可变的,这使得它更加困难,这也是故意的。:-)加载/保存blob字段的数量。对于对象,您需要完全不同的东西。您的任务包括两个步骤,对象反序列化和保存/加载到BLOB字段。我已经说过(还有@TLama),您不能直接将对象存储到BLOB字段,因此没有正确的语法。在这里搜索
[delphi]序列化
。我按照您的说明进行了操作,现在一切正常。TMyObject现在有SaveToStream和LoadFromStream,我将它们与从CreateBlobStream获得的流一起使用。关于如何保存名称字段有何评论?也许存在更现代的语法?代码在我的问题中。我遵循了你的指示,现在一切都很完美。TMyObject现在有SaveToStream和LoadFromStream,我将它们与从CreateBlobStream获得的流一起使用。关于如何保存名称字段有何评论?也许存在更现代的语法?代码在我的问题中。