1
votes

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 ?

1

1 Answers

0
votes

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 conversion1 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.