检测空/非空的TBlobField失败

3

我在一个DataSnap客户端应用程序中有一个TClientDataSet,其中包含类型为ftBlobfkInternal计算字段,其包含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),这个值仍然为true
我还尝试过检查SizeDataSizeBlobSize等属性,它们都为0。

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

*原因:我们不想把所有这些数据都拉进来;实际上,用许多blob加载TClientDataSet会在我们使用RemObjects组件时产生“包太大”的错误

编辑1:它可能与字段内容没有“粘合”有关——在代码的另一个部分直接跟随Post的lBlobField.Value为空。

编辑2:这是一个跨越3个嵌套表的查询数据集。DataSet是第三级TClientDataSet,这里的数据blob需要在被实际需要时才进行写入fkInternalCalc字段(因此有bmWrite、编辑和发布),通过一个单独的客户端服务器通道通过DownLoadAttachmentBlob检索。它把记录ID作为输入,并将blob数据放在第二个参数(lBlobStream)中。嵌套数据集包含第3级表的所有其他字段(如ID sExpItmFileID),但不包含其blob数据。DownLoadAttachmentBlob运行正常。
一旦一个blob被读入计算字段,我们想让它保持不变(不要两次检索它)。


1
抱歉如果听起来有些混乱,但是你使用bmWrite模式创建了Blob流,然而你似乎需要从中读取?另外,由于不确定DownLoadAttachmentBlob()函数的具体作用,blob字段是否正确为sExpItmFileFile但是你却将sExpItmFileID传递到该函数中? - Tom Brunberg
@TomBrunberg 对于混淆感到抱歉;-) 请查看编辑2。 - Jan Doggen
不要在您的帖子中随意添加“Edit1”和“Edit2”。我们可以通过查看修订历史记录来看到哪个编辑更改了什么。只需编辑帖子并按照您最初编写它们的方式添加详细信息即可。 - Ken White
2个回答

1

我自己找到了解决方案,但它完全让我困惑:

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

因此,相关的代码部分应该是:

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

1
这对我来说并不令人困惑。实际上,当TFileStream被释放时,它会将文件写入磁盘。 - Ken White

0

我会用SQL解决这个问题。

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

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

现在您可以查询BlobNull字段。显然,您需要调整IfNull函数以匹配数据库中可用的语法。 另一种选择可能是将测试作为布尔字段使用。
select *, (Blobfield is null) as BlobNull from mytable

更好的做法是不选择所有字段,而是只拉取所需的字段,并使用where子句排除已填充的blob字段,但我不确定您的用例是否允许这样做。

在SQL中解决这个问题的优点是,如果您不打算使用它们,就不必通过网络传输二进制大对象(BLOB),这可以大大加快速度。 - Johan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接