简体   繁体   English

使用FireDAC往返于数据库的Delphi流

[英]Delphi stream to/from database with FireDAC

Originaly I want to save/retrieve report from fastreports which uses SaveToStream/LoadToStream for this purpose. 本来我想从fastreports中保存/检索报告,为此它使用SaveToStream / LoadToStream。 I use RAD Studio XE6(upd1). 我使用RAD Studio XE6(upd1)。

In database I have table Reports with index field 'StVn'type int and field 'Definition' type ntext. 在数据库中,我有表Reports,索引字段为'StVn',类型为int,字段'Definition',类型为ntext。 Database is MSSQL and for saving report I use: 数据库是MSSQL,为了保存报告,我使用:

  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: 因此,我仅使用备忘录在新表单上做一个测试用例,并尝试使用相同的数据访问设置(FDConnection,FDCommand,FDQuery)和以下代码来保存/恢复它:

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). 如您所见,我已插入ShowMessage以查看保存和检索时的流大小,如果仅保存默认文本'Memo1',则保存时将得到7的长度,而加载备忘录时将得到14的长度(始终翻倍)。

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: 注意,由于我没有MSSQL,因此我尚未验证数据库的保存/加载,但是我很确定这是原因:

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. 默认情况下,TString使用默认编码(TEncoding.Default),这很可能是ANSI(在我的情况下是Windows-1252),因此,备注文本的长度显示为7个字节:“ Memo1”为5,CRLF为2 。

However, your column is of type NTEXT which stores text as UTF-16. 但是,您的列的类型为NTEXT,它将文本存储为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. 当您读回它时,您会将其视为斑点,并且FireDAC不会执行任何字符转换1 ,因此大小会加倍。

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. 我建议您将报告视为二进制数据,并使用“图像”类型列将其存储为此类,并使用ftBlob而不是ftWideMemo。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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