Database 如何在运行时更改Clientdataset字段数据类型
对于在设计时定义了字段的Delphi ClientDataSet,在运行时是否有方法更改特定字段的数据类型(更改cds.fields[n].datatype) 我有一个传统的Delphi7程序,在设计时设置了SQLDataSet和ClientDataSet字段(以覆盖各种属性) 它们连接到第三方Sybase SQL Anywhere 11数据库 最近,供应商将所有“描述”字段从VarChar(128)更改为long VarChar,但仅针对某些客户。因此,当我查询这些“描述”字段时,我的代码必须支持这两种类型的字段 我希望在类字段类型上设置条件编译(然后在打开SQL/客户机数据集之前添加字段),但是编译器忽略了类的组件定义部分中的{$IFDEF}条件(我越想,这就越有意义)Database 如何在运行时更改Clientdataset字段数据类型,database,delphi,dataset,tclientdataset,Database,Delphi,Dataset,Tclientdataset,对于在设计时定义了字段的Delphi ClientDataSet,在运行时是否有方法更改特定字段的数据类型(更改cds.fields[n].datatype) 我有一个传统的Delphi7程序,在设计时设置了SQLDataSet和ClientDataSet字段(以覆盖各种属性) 它们连接到第三方Sybase SQL Anywhere 11数据库 最近,供应商将所有“描述”字段从VarChar(128)更改为long VarChar,但仅针对某些客户。因此,当我查询这些“描述”字段时,我的代码必须
有几十个模块,数百个字段受到影响,因此任何见解都值得赞赏。我以前也遇到过这个问题,不是CD,而是设计时使用持久字段的TADODataSet。我认为下面的代码将帮助您了解如何修复/修补CD数据集 其思想是查询相关的表模式;获取实际的fileds数据类型;以及通过从数据集中取消附加持久字段并添加新的匹配持久字段来“更改”持久字段类型:
// TData class
procedure TData.DataModuleCreate(Sender: TObject);
var
I: Integer;
begin
for I := 0 to ComponentCount - 1 do
if (Components[I] is TCustomADODataSet) then
DataSetPrepareMemoFields(TDataSet(Components[I]));
end;
procedure TData.DataSetPrepareMemoFields(DataSet: TDataSet);
var
Fld: TField;
I: Integer;
FldName, CompName: string;
AOwner: TComponent;
begin
// Here you need to query the actual table schema from the database
// e.g. ADOConnection.GetFieldNames and act accordingly
// check which DataSet you need to change
// if (DataSet = dsOrders) or ... then...
if DataSet.FieldList.Count > 0 then
for I := DataSet.FieldList.Count - 1 downto 0 do
begin
if DataSet.FieldList.Fields[I].ClassNameIs('TMemoField') and (DataSet.FieldList.Fields[I].FieldKind = fkData) then
begin
// save TMemoField properties
AOwner := DataSet.FieldList[I].Owner;
CompName := DataSet.FieldList[I].Name;
FldName := DataSet.FieldList.Fields[I].FieldName;
// dispose of TMemoField
DataSet.FieldList[I].DataSet := nil; // Un-Attach it from the DataSet
// create TWideADOMemoField instead
Fld := TWideADOMemoField.Create(AOwner); // Create new persistent Filed instead
Fld.Name := CompName + '_W';
Fld.FieldName := FldName;
Fld.DataSet := DataSet;
end;
end;
end;
也就是说,在我解决了这个问题之后,我再也没有使用过持久字段。
我的所有字段都是在运行时生成的。包括计算/查找/内部字段。要么在运行时之前根本不添加该字段,然后在该点添加适当的类型,要么在运行时删除它(如果需要),然后重新添加所需类型的新字段。@KenWhite说了什么。它应该可以正常工作,但如果有问题的字段具有对应的FieldDef,则需要删除并重新创建该字段,否则在打开CD时,可能会出现错误,抱怨FieldDef中定义的数据类型与替换的TField之间不匹配。就我个人而言,我倾向于重新创建所有字段/fielddef,而不仅仅是涉及的字段。不幸的是,数据库的更改比我最初想象的要多——这可能涉及1000个字段(跨多个项目)。它也有副作用——我广泛使用DBgrids——我得到的是(备忘录)而不是数据。我可以设置字段的OnGetText-但同样,有很多字段。。。CDS是在设计时定义的,但是我动态地创建了SQL——我正在考虑在SQL中对VARCHAR进行强制转换/转换。嗯,字段[n]可能有问题。数据大小例如-将一个长varchar强制转换到CD中最初定义为varchar[128]的字段中…@MartynA-我从SDS和CD中删除了该字段。然后使用条件编译1)将适当的字段/类型添加到公共声明中;2)添加SDS字段定义;和,3)添加CDS字段DEF和字段。工作很好,但当然,现在网格中有一个“备忘录”。我有一种感觉,我会“分叉”代码…“分叉地狱”,我想你可能会说(对不起,无法抗拒)。说真的,我想得越多,我就越倾向于避免任何持久性字段/字段定义:要么在代码中创建它们,要么让CDS通过SDS从服务器获得的内容来创建它们。我已经完成了转换,但这看起来很有趣。我可以看到问题,因为我通过自动声明引用了字段——例如在datamodule类声明中,我有myStringField:TStringField;如果我像上面那样替换数据类型,我想我可能仍然会看到不兼容的类型错误。我需要一周左右的时间才能回到这个话题上。现在-谢谢!我正在尝试这种技术,但它不允许我在数据集打开时添加字段,也不允许我在数据集关闭时访问字段