检测 empty/filled TBlobField 失败

Detecting empty/filled TBlobField fails

我有一个 fkInternal 类型 ftBlob 的计算字段(在 TClientDataSet 中),其中包含 DataSnap 客户端应用程序中的 blob。

该字段最初是空的,我们只在实际需要 blob 数据时才填充它*.

这是从服务器应用程序中提取数据的代码:

var
  lBlobStream: TStream;
  lBlobField : TBlobField;

with DataSet do
begin
  lBlobField := TBlobField(FieldByName(sExpItmFileFile)); // The fkInternalCalc blob
  try
    // Retrieve the blob stream (calculated field) separately when we don't yet have data:
    if lBlobField.isNull then
    begin
      Edit;
      lBlobStream := CreateBlobStream(lBlobField, bmWrite);
      DownLoadAttachmentBlob(FieldByName(sExpItmFileID).Asinteger,lBlobStream);
      Post;
      ...
    end;

blob 数据检索正常。
我的问题是 if lBlobField.isNull 测试:下次我们进入这段代码时(数据集保留在同一条记录上,同时没有调用 ApplyUpdates 这个值仍然是真.
我也尝试检查属性 SizeDataSizeBlobSize,它们都是 0.

如何检查我的 TBlobField 是否包含数据?
(或者我在这段代码中做错了什么?)

* 原因:我们不想把所有这些数据都拉进来;实际上加载带有许多 blob 的 TClientDataSet 会在我们使用的 RemObjects 组件中产生 'package too large' 错误

编辑 1:它可能与字段的内容有关,而不是 'sticking' - 在紧跟在 Post lBlobField.Value 之后的代码的另一部分是空的。

编辑 2:这是一个包含 3 个嵌套 table 查询的数据集。 DataSet 是第三层 TClientDataSet,这里需要将数据 blob 写入 fkInternalCalc 字段(因此 bmWrite、Edit 和Post), 仅在实际需要时才使用。 DownLoadAttachmentBlob 通过单独的客户端-服务器通道检索它们。这将获取记录 ID 作为输入并将 blob 数据放入第二个参数 (lBlobStream)。 (嵌套)数据集包含第 3 级 table(如 ID sExpItmFileID)的所有其他字段,但不包含其 blob 数据。 DownLoadAttachmentBlob 工作正常。
一旦将 blob 读入 calc 字段,我们希望保留它(而不是检索它两次)。

我会在 SQL 中解决这个问题。

在您的 select 语句中添加一个额外的字段,详细说明 blob 字段是否为空。

select *, ifnull(BlobField, 1, 0) as BlobNull from mytable

现在您可以只查询 BlobNull 字段。显然,您必须调整 IfNull 函数以匹配数据库中可用的语法。 另一种方法可能是将测试用作布尔字段。

select *, (Blobfield is null) as BlobNull from mytable

更好的做法是不要 select 所有字段,而只是拉入所需的字段并使用 where 子句排除填充的 blobfields,但我不确定您的用例是否允许这个。

自己找到了解决方案,这让我很困惑:

必须在调用数据集 Post 方法之前释放 TStream (var lBlobStream)。

所以相关代码部分应该是:

Edit;
lBlobStream := CreateBlobStream(lBlobField, bmWrite);
DownLoadAttachmentBlob(FieldByName(sExpItmFileID).Asinteger,lBlobStream);
lBlobStream.Free;
Post;