1

我使用 TField.origin 属性为 SQL 查询动态构建 where 子句。

所以,如果我有这样的查询;

select
  p.firstname,
  p.lastname,
  g.description
from
  people p
  inner join groups g

我可以将名字字段的来源设置为;

FirstNameField.origin = 'p.firstname';

然后在动态查询的 where 子句中使用它,例如;

SQLWhere = 'where ' + FirstNameField.origin + ' = ''' + MyValue + ''' ';

(显然我有额外的代码来防止 SQL 注入)。

我一直这样做,效果很好。然而,当试图追踪一个错误时,我注意到我有一个数据集不断将原点的值重置为;

people.firstname

代替;

p.firstname

我追踪到数据集关闭然后重新打开的时间。但是我一直这样做,所以我不明白为什么一个数据集有不同的行为。

我的问题是如何防止原始值被重置?

4

1 回答 1

3

下面的代码来自 D7 的 IBCustomDataSet 单元(代码在以后的 XEx 版本中更复杂)。

正是这段代码设置Origin了 IBX TField 的属性。

如果其字段为 True,则当数据集调用其InternalOpen 方法时,将调用 TIBCustomDataSet.CreateFields。FDefaultFields如果在数据集的条目上InternalOpen 为零FieldCount,则为 True。FieldCount如果事先没有在用户代码中或在 IDE 中使用数据集上的字段编辑器创建任何字段,则将为零。 InternalOpen由 TDataSet.Open 通过其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;

更新 TIBCustomDataSet.InternalOpen 的实现显然在 XE4 和 XE6 之间发生了变化,因此现在无条件调用 CreateFields(即不管 DefaultFields 是否为 True)。因此,拥有已经存在的 TFields 不会避免调用 CreateFields 并因此重置 Origin 属性。

于 2015-08-27T17:41:28.867 回答