我有一个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
)此值仍然为真< / em>的。
我还尝试检查属性Size
,DataSize
,BlobSize
,它们都是0。
如何检查我的TBlobField是否包含数据?
(或者我在这段代码中做错了什么?)
*原因:我们不想把所有这些数据都拉进来;实际加载带有许多blob的TClientDataSet
会在我们使用的RemObjects组件中出现“包太大”错误
编辑1:它可能与字段内容没有“粘贴”有关 - 在帖子lBlobField.Value
之后的代码的另一部分是空的。
编辑2:这是一个跨3个嵌套表进行查询的数据集。 DataSet
是第三级TClientDataSet
,此处数据blob需要写入 fkInternalCalc字段(因此bmWrite
,编辑和帖子),只有当他们真正需要时。它们由DownLoadAttachmentBlob
通过单独的客户端 - 服务器通道检索。这将记录ID作为输入,并将blob数据放在第二个参数(lBlobStream
)中。 (嵌套)数据集包含第3级表的所有其他字段(如ID sExpItmFileID
),但不包含其blob数据。 DownLoadAttachmentBlob
工作正常。
一旦blob被读入calc字段,我们希望将其保留(不检索两次)。
答案 0 :(得分:1)
我自己找到了解决方案,这让我很困惑:
在调用Dataset Post方法之前,必须释放TStream
(var lBlobStream
)。
所以相关的代码部分应该是:
Edit;
lBlobStream := CreateBlobStream(lBlobField, bmWrite);
DownLoadAttachmentBlob(FieldByName(sExpItmFileID).Asinteger,lBlobStream);
lBlobStream.Free;
Post;
答案 1 :(得分:0)
我会在SQL中解决这个问题。
在select语句中添加一个额外字段,详细说明blob字段是否为空。
select *, ifnull(BlobField, 1, 0) as BlobNull from mytable
现在您只需查询BlobNull
字段即可。显然,您必须调整IfNull
函数以匹配数据库中可用的语法。
另一种方法是将测试用作布尔字段。
select *, (Blobfield is null) as BlobNull from mytable
更好的方法是不选择所有字段,只需拉入所需的字段并使用where
子句排除填充的blobfields,但我不确定您的用例是否允许这样做。