我使用TField.origin属性为SQL查询动态构建where子句。
所以,如果我有一个查询,如;
select
p.firstname,
p.lastname,
g.description
from
people p
inner join groups g
我可以将firstname字段的来源设置为;
FirstNameField.origin = 'p.firstname';
然后在动态查询的where子句中使用它,例如;
SQLWhere = 'where ' + FirstNameField.origin + ' = ''' + MyValue + ''' ';
(显然我有额外的代码来防止SQL注入)。
我一直这样做,效果很好。然而,当我试图追踪一个错误时,我注意到我有一个数据集不断重置原点的值,例如回到;
people.firstname
而不是;
p.firstname
我将其追踪到数据集关闭然后重新打开的时间。但是我一直这样做,所以我无法理解为什么一个数据集有不同的行为。
我的问题是如何防止原点值被重置?
答案 0 :(得分:3)
下面的代码来自D7的IBCustomDataSet单元(后面的代码更复杂 XEx版本)。
这段代码设置了IBX TField的Origin
属性。
当数据集调用InternalOpen
时,将调用TIBCustomDataSet.CreateFields
方法,如果其FDefaultFields
字段为True。如果进入InternalOpen
,它将为True
数据集的FieldCount
为零。如果没有字段,FieldCount
将为零
已使用“字段”编辑器在用户代码或IDE中预先创建
在数据集上。 TDataSet.Open通过其InternalOpen
方法调用OpenCursor
。
因此,避免执行'CreateFields'的方法和数据集字段'Origin
因此重置属性是使用这些方法之一(IDE或用户代码)
在打开数据集之前创建字段。换句话说,如果您通过这些方法中的任何一种设置Origin
属性,那么应该避免它被重置。
procedure TIBCustomDataSet.CreateFields;
var
FieldAliasName, RelationName : String;
i : Integer;
f : TField;
begin
inherited;
for i := 0 to FQSelect.Current.Count - 1 do
with FQSelect.Current[i].Data^ do
begin
{ Get the field name }
SetString(FieldAliasName, aliasname, aliasname_length);
SetString(RelationName, relname, relname_length);
f := FindField(FieldAliasname);
if Assigned(f) then
begin
if (RelationName <> '') and (FieldAliasName <> '') then
f.Origin := RelationName + '.' + FieldAliasName;
end;
end;
end;
更新在XE4和XE6之间显然改变了TIBCustomDataSet.InternalOpen的实现,因此现在无条件地调用CreateFields(即,无论DefaultFields是否为True)。因此,拥有已存在的TField将不会避免调用CreateFields,因此会重置Origin属性。