【问题标题】:Delphi - How to get dataset's OldValue and NewValue for blob field as streamsDelphi - 如何将 blob 字段的数据集的 OldValue 和 NewValue 作为流
【发布时间】:2013-10-31 15:23:14
【问题描述】:

在 Delphi XE 上,我使用来自 TpFIBDataSet 的 OldValueNewValue(但它可以应用于任何 TDataSet 后代),以验证不同字段是否已更改。我的问题是如何将 blob 字段的这两个值检索为 TMemoryStreams?我做了一些研究,但我什么也没找到。

【问题讨论】:

  • 我不知道用本机代码来做这件事。您是否考虑过实现自己的子类来模仿旧值和新值的行为,但返回 TBytes 而不是 Variant
  • 我也在考虑这个问题。我的问题是我不能同时拥有旧流和新流。假设在该二进制流中,您有一个 RTF 文件或图像文件。如何在不进行补充查询的情况下验证新的与旧的?
  • 我想我找到了一种方法来检测 BLOB 是否已更改,因为您不能将 OldValueNewValue 用于 BLOB。我会发布它作为答案。
  • 如果您只想检测 BLOB 何时被修改,那么旧值和新值有什么关系?只需使用 .Modified 属性即可。
  • 如果您出于其他原因需要旧值和新值,那么您必须对数据集组件进行子类化并编写新代码以将 BLOB 作为字节而不是变体返回,或者存储之前的在用户编辑它之前在内存流中,以便您拥有之前和之后,或者克隆(或复制)数据集,以便在用户更改它们之前拥有旧值的副本。如果您说明您打算如何使用新旧流,我或许可以提供更多信息。

标签: delphi blob firebird delphi-xe


【解决方案1】:

我使用例程来检测字段是否更改,因此我可以将发送到数据库的字段限制为仅更改的字段。我今天在该例程中添加了代码来处理 BLOB 字段,因为它们无法返回 .AsVariant,这就是 OldValueNewValue 的返回方式。我还没有用我所有的用例测试过这个,但到目前为止它看起来很可靠。

function FieldChanged(DataSet: TDataSet; FieldName: string): Boolean;
var
  fld: TField;
begin
  fld := DataSet.FieldByName(FieldName);

  if fld.IsBlob then
    Exit((fld as TBlobField).Modified);

  if (fld.OldValue = Null) and (fld.NewValue = Unassigned) then // This happens when a NULL field does not change
    Exit(False)
  else
    Exit(fld.OldValue <> fld.NewValue);
end;

【讨论】:

  • 如果fldnvarchar(max)xml 类型,它也会评估为BLOB,这对于检测修改的值非常有效。
  • +1 我什至没有意识到 TBlobField 有一个 Modified 属性。
  • 好的。因此,仅当 blob 字段已更改时才会显示。
  • 这就是我理解的方式。如果 BLOB 字段发生变化,Modifiedtrue,否则为 false。所以你不知道它是如何被修改的,但至少你知道如果它改变了,这就是我理解你想知道的[为了验证不同的字段是否改变了]。
  • 我知道 Modified 属性,以及它是如何工作的。我问如何检索该字段的旧值和新值。 “我的问题是如何将 blob 字段的这两个值检索为 TMemoryStream”。感谢您的努力,答案将帮助其他人查看是否修改了 blob 字段。
【解决方案2】:

我是这样做的:

var
  stream: TBytesStream;
begin
  if not DataSet.FieldByName('blobfield').IsNull then
  begin
    stream := TBytesStream.Create(DataSet.FieldByName('blobfield').AsBytes);
    // do something with the stream
    FreeAndNil(stream);
  end;
end;

我更喜欢使用TBytesStream,因为它完成了与我通常使用TMemoryStream 相同的事情,并且如果您查看它的构造函数,它不会像TMemoryStream 那样重新分配内存并将二进制数据复制到它.

如果您确实需要使用TMemoryStream,您可以使用TBytesStream.SaveToStream() 方法轻松地将TBytesStream 保存到TMemoryStream

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-27
    • 1970-01-01
    • 2015-08-02
    • 2021-06-09
    • 1970-01-01
    • 2011-12-14
    • 1970-01-01
    • 2019-02-10
    相关资源
    最近更新 更多