【问题标题】:How can I add fields to a clientdataset at runtime?如何在运行时向客户端数据集添加字段?
【发布时间】:2011-06-23 11:25:33
【问题描述】:

我有一个TClientDataSet,它由TTable 的数据集提供。 数据集有两个字段:postalcode(string, 5) 和 street(string, 20)

在运行时我想显示第三个字段(字符串,20)。该字段的例程是获取邮政编码作为参数,并返回属于该邮政编码的城市。

问题只是将计算字段添加到已经存在的字段。填充数据本身不是问题。

我试过了:

  cds.SetProvider(Table1);
  cds.FieldDefs.Add('city', ftString, 20);

  cds.Open;

  cds.Edit;
  cds.FieldByName('city').AsString := 'Test';  // --> errormessage (field not found)
  cds.Post;

cds是我的clientdataset,Table1是一个悖论表,但是其他数据库的问题是一样的。

提前致谢

【问题讨论】:

标签: database delphi dataset tclientdataset


【解决方案1】:

你应该在添加字段后使用CreateDataset

cds.SetProvider(Table1);
cds.FieldDefs.Add('city', ftString, 20);
cds.CreateDataset; 

cds.Open;
cds.Edit;
cds.FieldByName('city').AsString := 'Test';  
cds.Post;

【讨论】:

    【解决方案2】:

    希望为不存在的字段分享更准确的查询。我敢打赌最好使用演员表,不要使用空格!

    select E.NAME, E.SURNAME, cast(null as varchar(20)) as CITY
    from EMPLOYEE E
    

    例如| Marc'O | Polo | <NULL> |

    更准确,可以明确看到字段大小,易懂、简单、安全!

    【讨论】:

      【解决方案3】:

      如果您想将已经存在的“动态”数据字段(来自提供者端)与其他客户端持久字段(计算、查找、内部计算、聚合)结合起来,您应该将 CDS 子类化。只需引入额外的布尔属性 CombineFields 并使用以下行覆盖 BindFields(在较新的 delphi 版本中)或整个 InternalOpen(就像我在 d2006/2007 中所做的那样)

      如果 DefaultFields 或 CombineFields 则 CreateFields; { TODO -ovavan -cSIC : 如果 CombineFields 为真,那么持久字段将与默认字段共存 }

      这将使您避免所有运行时与 FieldDefs/CreateField 的混乱

      【讨论】:

        【解决方案4】:

        好吧,我找到了一个更简单的解决方案,因为我的 sql 中有 24 个字段,我不想手动添加它们,所以我在 sql 语句中添加了一个虚拟字段,而不是像:

        select '      ' as city, the rest of the fields ... 
        

        我可以在我的程序 OnAfterOpen 事件中进行修改。

        我必须在 sql 中定义该字段的长度,方法是留出足够的空格,例如 5 个空格代表 5 个字符,所以我必须知道城市名称可以有多长。

        【讨论】:

        • 这可能看起来不优雅,但它很容易实现。
        【解决方案5】:

        如果要添加基础数据中不存在的其他字段,则还需要手动添加现有字段。添加字段时需要关闭数据集,但如果您不想手动跟踪所有字段详细信息,则可以使用FieldDefs.Update 获得必要的元数据。基本上是这样的:

        var
          i: Integer;
          Field: TField;
        begin    
          cds.SetProvider(Table1);
        
          // add existing fields
          cds.FieldDefs.Update;
          for i := 0 to cds.FieldDefs.Count - 1 do 
            cds.FieldDefs[i].CreateField(cds);
        
          // add calculated field
          Field := TStringField.Create(cds);
          Field.FieldName := 'city';
          Field.Calculated := True;
          Field.DataSet := cds;
        
          cds.Open;
        end;
        


        另请参阅excellent articleCary Jensen

        【讨论】:

        • 感谢您的回答和不错的链接,我试试这个,尽管我必须手动在我的 sql 中添加所有文件。
        猜你喜欢
        • 2016-10-29
        • 2018-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-21
        • 2022-01-04
        • 2017-04-17
        相关资源
        最近更新 更多