database 如何在运行时向 clientdataset 添加字段?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4934103/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I add fields to a clientdataset at runtime?
提问by CloudyMarble
I have a TClientDataSet
, which is provided by a TTable
's dataset.
The dataset has two fields: postalcode (string, 5) and street (string, 20)
我有一个TClientDataSet
,它由 aTTable
的数据集提供。数据集有两个字段:邮政编码(字符串,5)和街道(字符串,20)
At runtime I want to display a third field (string, 20). The routine of this field is getting the postalcode as a parameter and gives back the city belongs to this postalcode.
在运行时,我想显示第三个字段(字符串,20)。该字段的例程是获取邮政编码作为参数,并返回属于该邮政编码的城市。
The problem is only about adding a calculated field to the already existing ones. Filling the data itself is not the problem.
问题仅在于向现有字段添加计算字段。填充数据本身不是问题。
I tried:
我试过:
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 is my clientdataset, Table1
is a paradox Table, but the problem is the same with other databases.
cds 是我的clientdataset,Table1
是一个悖论表,但是问题和其他数据库一样。
Thanks in advance
提前致谢
回答by Sertac Akyuz
If you want to add additional fields other than those exist in the underlying data, you need to also add the existing fields manually as well. The dataset needs to be closed when you're adding fields, but you can have the necessary metadata with FieldDefs.Update
if you don't want to track all field details manually. Basically something like this:
如果要添加基础数据中存在的字段以外的其他字段,还需要手动添加现有字段。添加字段时需要关闭数据集,但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;
Also see this excellent articleby Cary Jensen.
另请参阅Cary Jensen撰写的这篇优秀文章。
回答by CloudyMarble
Well i found a simpler solution, as i have 24 fields in my sql i didnt wanted to add them all manually so i added a dummy field to the sql statement instead like:
好吧,我找到了一个更简单的解决方案,因为我的 sql 中有 24 个字段,我不想手动添加它们,所以我在 sql 语句中添加了一个虚拟字段,而不是:
select ' ' as city, the rest of the fields ...
which i can modify in my program OnAfterOpen event.
我可以在我的程序 OnAfterOpen 事件中修改它。
Well i had to define in the sql how long that field should be by leaving enough empty spaces, for instance 5 empty spaces for 5 characters, so i must know how long the city name could be.
好吧,我必须在 sql 中通过留下足够的空格来定义该字段的长度,例如 5 个空格对应 5 个字符,所以我必须知道城市名称可以有多长。
回答by xoxn-- 1'w3k4n
Would like to share more accurate Query for unexisting fields. I bet it's better to use cast, neither spaces!
想为不存在的字段分享更准确的查询。我敢打赌最好使用演员表,而不是空格!
select E.NAME, E.SURNAME, cast(null as varchar(20)) as CITY
from EMPLOYEE E
e.g. | Marc'O | Polo | <NULL> |
例如 | Marc'O | Polo | <NULL> |
It's more accurate, can definetly see field size, understandable, easy, safe!
它更准确,可以明确看到字段大小,易懂,简单,安全!
回答by Morteza Esmizadeh
You should use CreateDataset
after add field:
您应该CreateDataset
在添加字段后使用:
cds.SetProvider(Table1);
cds.FieldDefs.Add('city', ftString, 20);
cds.CreateDataset;
cds.Open;
cds.Edit;
cds.FieldByName('city').AsString := 'Test';
cds.Post;
回答by vavan
if you want to combine already existing "dynamic" data fields (from provider side) with additional client side persistent fields (calculated, lookup, internalcalc, aggregate) you should subclass CDS. just introduce extra boolean property CombineFields and either override BindFields (in newer delphi versions) or the entire InternalOpen (as I did in d2006/2007) with the following line
如果您想将已经存在的“动态”数据字段(来自提供方)与附加的客户端持久字段(计算、查找、内部计算、聚合)结合起来,您应该子类化 CDS。只需引入额外的布尔属性 CombineFields 并使用以下行覆盖 BindFields(在较新的 delphi 版本中)或整个 InternalOpen(就像我在 d2006/2007 中所做的那样)
if DefaultFields or CombineFields then CreateFields; { TODO -ovavan -cSIC : if CombineFields is true then persistent fields will coexist with Default ones }
如果 DefaultFields 或 CombineFields 则 CreateFields;{ TODO -ovavan -cSIC : 如果 CombineFields 为真,那么持久字段将与默认字段共存 }
that will allow you to avoid all that runtime mess with FieldDefs/CreateField
这将允许您避免使用 FieldDefs/CreateField 的所有运行时混乱