8°

关于TField.DataSize的坑

在从数据库中查询数据时,有时需要事先取得字段内容的大小,再根据情况进行处理。

对于ADO之类返回TField类型的,可以使用DataSize属性,但是!!!这里有很深的坑!!!

首先看如下代码:

if ADOQuery.FieldByName('Test').DataSize > 3 then
  {处理1}
else
  {处理2};

按预想,当Test字段里的数据超过3B时,应该执行处理1的代码,但事实上无论该内容长短,都是执行处理2的代码,WHY?

扒一下Delphi的源码就明白了。

function TField.GetDataSize: Integer;
begin
  Result := 0;
end;

function TStringField.GetDataSize: Integer; begin Result := Size + 1; end;

function TWideStringField.GetDataSize: Integer; begin Result := (Size + 1) * SizeOf(WideChar); end;

function TIntegerField.GetDataSize: Integer; begin Result := SizeOf(Integer); end;

function TLongWordField.GetDataSize: Integer; begin Result := SizeOf(LongWord); end;

function TSmallintField.GetDataSize: Integer; begin Result := SizeOf(SmallInt); end;

function TShortintField.GetDataSize: Integer; begin Result := SizeOf(ShortInt); end;

function TByteField.GetDataSize: Integer; begin Result := SizeOf(Byte); end;

function TLargeintField.GetDataSize: Integer; begin Result := SizeOf(Largeint); end;

function TWordField.GetDataSize: Integer; begin Result := SizeOf(Word); end;

function TFloatField.GetDataSize: Integer; begin Result := SizeOf(Double); end;

function TSingleField.GetDataSize: Integer; begin Result := SizeOf(Single); end;

function TExtendedField.GetDataSize: Integer; begin Result := SizeOf(Extended); end;

function TBooleanField.GetDataSize: Integer; begin Result := SizeOf(WordBool); end;

function TDateTimeField.GetDataSize: Integer; begin Result := SizeOf(TDateTime); end;

function TSQLTimeStampField.GetDataSize: Integer; begin Result := SizeOf(TSQLTimeStamp); end;

function TSQLTimeStampOffsetField.GetDataSize: Integer; begin Result := SizeOf(TSQLTimeStampOffset); end;

function TDateField.GetDataSize: Integer; begin Result := SizeOf(Integer); end;

function TTimeField.GetDataSize: Integer; begin Result := SizeOf(Integer); end;

function TBytesField.GetDataSize: Integer; begin Result := Size; end;

function TVarBytesField.GetDataSize: Integer; begin Result := Size + SizeOf(Word) {Length Prefix}; end;

function TBCDField.GetDataSize: Integer; begin // SizeOf(TBcd) is used here instead of SizeOf(Currency) because some // datasets store the currency data in TBcd format in the record buffer. // For these classes (TBDEDataset & TClientDataset) a call to // TField.GetData(Buffer, True) will return a TBcd. Result := SizeOf(TBcd); end;

function TFMTBCDField.GetDataSize: Integer; begin Result := SizeOf(TBcd); end;

function TBlobField.GetDataSize: Integer; begin // Blob data is not stored in the record buffer and can not be read // with a call to TField.GetData. Use GetBlobSize instead. Result := 0; end;

function TReferenceField.GetDataSize: Integer; begin Result := FSize + 2; end;

也就是说,不能直接取DataSize,而是需要转换为实际的类型后再取DataSize,而且TBlobField是特例,需要使用TBlobField.BlobSize。那么,刚才的例子应该这样写(假设字段类型是Blob):

if TBlobField(ADOQuery.FieldByName('Test')).BlobSize > 3 then
  {处理1}
else
  {处理2};

本文由【天朝八阿哥】发布于开源中国,原文链接:https://my.oschina.net/u/209067/blog/3073039

全部评论: 0

    我有话说: