简体   繁体   中英

Delphi stream to/from database with FireDAC

Originaly I want to save/retrieve report from fastreports which uses SaveToStream/LoadToStream for this purpose. I use RAD Studio XE6(upd1).

In database I have table Reports with index field 'StVn'type int and field 'Definition' type ntext. Database is MSSQL and for saving report I use:

  FDCommand.CommandText.Text:='UPDATE Reports SET Definition= :pDefinition WHERE StVn=1';
  FDCommand.Params.ParamByName('pDefinition').LoadFromStream(MyStream, ftWidememo);
  FDCommand.Execute;

and for retrieving:

  FDQuery.SQL.Text:='SELECT * FROM Reports WHERE StVn=1';
  FDQuery.Open();
  MyStream:=FDQuery.CreateBlobStream(FDQuery.FieldByName('Definition'),bmRead);

This worked for some short reports, but for any real one saving/restoring corrupts report definition.

So I make an test case on new form with just an Memo and tried to save/restore it with same data acess setup (FDConnection, FDCommand, FDQuery) and following code:

procedure TForm1.BMemoSaveClick(Sender: TObject);
var TmpStream:TStream;
begin
  TmpStream:=TMemoryStream.Create;
  Memo1.Lines.SaveToStream(TmpStream);
  ShowMessage(IntToStr(TmpStream.Size));
  FDCommand1.Params.Clear;
  FDCommand1.CommandText.Text:='UPDATE Reports SET Definition= :pDefinition WHERE StVn=1';
  FDCommand1.Params.ParamByName('pDefinition').LoadFromStream(TmpStream,ftWideMemo);
  FDCommand1.Execute();
  TmpStream.Free;
end;

procedure TForm1.BMemoLoadClick(Sender: TObject);
var TmpStream:TStream;
begin
  FDQuery.SQL.Text:='SELECT * FROM Reports WHERE StVn=1';
  FDQuery.Open();
  TmpStream:=FDQuery.CreateBlobStream(FDQuery.FieldByName('Definition'),bmRead);
  ShowMessage(IntToStr(TmpStream.Size));
  Memo1.Lines.LoadFromStream(TmpStream);
  TmpStream.Free;
end;

As you can see I have inserted ShowMessage to see the stream size at saving and at retrieving and if I save just default text 'Memo1' I get length of 7 at saving and length of 14 at loading the memo (it is allways doubled).

Any ideas what I am doing wrong ?

Note, I have not verified the database saving/loading as I don't have MSSQL, but I'm pretty sure this is the cause:

By default, TString uses the default encoding (TEncoding.Default), which is most likely ANSI (in my case Windows-1252), hence the length for the memo text showing as 7 bytes: 5 for "Memo1" and two for the CRLF.

However, your column is of type NTEXT which stores text as UTF-16. When you read it back you do so as a blob and FireDAC does not perform any character conversion 1 then, hence the doubling in size.

I would suggest you treat the report as binary data and store it as such using an "image" type column and use ftBlob instead of ftWideMemo.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM