【发布时间】:2020-06-24 21:29:11
【问题描述】:
短版
我怎么称呼:
dataset1.FieldByName(fieldName).AsString := 'Something';
它工作了吗?
加长版
我有一个DataSet:
var
ds: TDataSet;
ds := GetSomeSortOfDataSetFromSomewhere();
此数据集将被导出(例如导出到 Excel、cSV、TSV、Markdown、HTML、XML):
ExportDataSet(ds);
并且导出将包含所有列和所有行:
| Username | Fullname |
|---|---|
| ian | IAN BOYD |
| MartynA | MARTIN |
| ngal | NASREDDINE GALFOUT |
| uewr | UWE RAABE |
现在我想修改每一行的Fullname 字段在内存中,然后再用它做其他事情(即它永远不会回到数据库中,我不知道它来自哪里from ,它可能不是来自数据库):
while not ds.EOF do
begin
ds.FieldByName('Fullname').AsString := FormatNamePrettyLike(ds.FieldByName('Fullname').AsString;
ds.Next;
end;
尝试修改字段会出现异常:
解决方案是将数据集克隆到内存中TClientDataset:
///<summary>Clones a dataset into a TClientDataSet; which is an editable in-memory DataSet.</summary>
function CloneDataSet(dsSource: TDataSet): TDataSet; //TDataSet > TCustomClientDataSet > TClientDataSet
var
tempProvider: TDataSetProvider;
data: OleVariant;
ds: TClientDataSet;
begin
tempProvider := TDataSetProvider.Create(nil);
try
tempProvider.DataSet := dsSource;
data := tempProvider.Data;
finally
tempProvider.Free;
end;
ds := TClientDataSet.Create(nil);
ds.Data := data;
Result := ds;
end;
这给出了更大的代码:
var
ds: TDataset;
dsEditable: TDataSet;
ds := GetDataSomeOfSomeSortFromSomewhere();
//Clone to dataset to an in-memory dataset so we can modify it.
dsEditable := CloneDataSet(ds);
ds.Free;
ds := edEditable;
while not ds.EOF do
begin
ds.FieldByName('Fullname').AsString := FormatNamePrettyLike(ds.FieldByName('Fullname').AsString;
ds.Next;
end;
但这给出了错误:
解决办法是put the dataset in edit mode:
//The in-memory ClientDataSet won't be editable until you mark it editable.
ds.Edit;
///<summary>Clones a dataset into a TClientDataSet; which is an editable in-memory DataSet.</summary>
function CloneDataSet(dsSource: TDataSet): TDataSet; //TDataSet > TCustomClientDataSet > TClientDataSet
var
tempProvider: TDataSetProvider;
data: OleVariant;
ds: TClientDataSet;
begin
tempProvider := TDataSetProvider.Create(nil);
try
tempProvider.DataSet := dsSource;
data := tempProvider.Data;
finally
tempProvider.Free;
end;
ds := TClientDataSet.Create(nil);
ds.Data := data;
//The in-memory ClientDataSet won't be editable until you mark it editable.
ds.Edit;
Result := ds;
end;
现在重复练习会出现错误:
字段
Fullname不能修改。
解决办法是set Field.ReadOnly to false:
//Even after marking the in-memory data-set as editable, you still can't edit it
//until you mark all fields as editable.
for i := 0 to ds.FieldCount-1 do
ds.Fields[i].ReadOnly := False;
///<summary>Clones a dataset into a TClientDataSet; which is an editable in-memory DataSet.</summary>
function CloneDataSet(dsSource: TDataSet): TDataSet; //TDataSet > TCustomClientDataSet > TClientDataSet
var
tempProvider: TDataSetProvider;
data: OleVariant;
ds: TClientDataSet;
begin
tempProvider := TDataSetProvider.Create(nil);
try
tempProvider.DataSet := dsSource;
data := tempProvider.Data;
finally
tempProvider.Free;
end;
ds := TClientDataSet.Create(nil);
ds.Data := data;
//The in-memory ClientDataSet won't be editable until you mark it editable.
ds.Edit;
//Even after marking the in-memory data-set as editable, you still can't edit it
//until you mark all fields as editable.
for i := 0 to ds.FieldCount-1 do
ds.Fields[i].ReadOnly := False;
Result := ds;
end;
重复练习会出现错误:
试图修改只读字段。
所以我放弃了。如何编辑数据集字段?
克隆的内存中的TCustomClientDataSet 内容都在那里;我只是想在客户端上编辑它们以供显示。
奖金聊天
显然我不能向数据集添加新列:
| Username | Fullname | PrettyFullname |
|---|---|---|
| ian | IAN BOYD | Ian Boyd |
| MartynA | MARTIN | Martin |
| ngal | NASREDDINE GALFOUT | Nasreddine Galfout |
| uewr | UWE RAABE | Uwe Raabe |
显然我无法将事件处理程序附加到数据集:
- 因为当数据集传递给链中的下一个人(例如线程)时,该数据处理程序将无效,并释放原始表单
- 这也不是我要问的;这是关于修改数据集的内容
- 值的更新会影响其他系统(例如数据库、Web 服务等)。我希望更改完成一次,然后进入数据集
【问题讨论】:
-
您应该调用 DataSet.Edit 将数据集置于 dsEdit 状态,然后再尝试修改字段,然后调用 DataSet.Post 将当前记录的更改发布回数据集,然后再移动到下一个。实际上,移动数据集光标(通过调用 Next、Prior、First 等)将隐式发布任何待处理的更改,但最好不要依赖于此。最好在表单/数据模块上使用 DSP 和 CDS 组件,因为它可能更容易找到您的问题。在 CDS 中编辑数据应该“正常工作”,除非 [继续]
-
您的 DSP 正在从只读源获取数据。在您的位置上,我会将事情归结为一个最小的示例并对其进行调试 - 它实际上不应该超过大约 10 行代码,而不是您似乎拥有的熨平板。顺便说一句,如果 DSP 源是 Sql 数据集,则 DSP 足够智能,可以生成用于发出 UPDATE 语句的代码以强制执行更改,即使源名义上是只读查询结果。
-
PS 不要忘记在 CDS 上调用 ApplyUpdates,否则它们不会。
-
@MartynA 这不是 OP 所要求的。他说这些名字不会被发布到数据库中。他想修改它们以供展示。
-
我认为@Sertac 的重点在于,如果您只是想对
FullName进行美化演示以用于显示目的,请简化将 fkInternalCalc 字段添加到 CDS 并将其值格式化为您想要在OnCalcFields事件中 - 那么,根本不需要在代码中遍历 CDS,这一切都在幕后完成。但是当然可能可以编辑 CDS 中的记录,这就是它们的全部意义所在。并且 DSP 提供了一种将更改反馈到底层数据集的方法即使如果它是从提供只读结果集的 SQL 查询中获得的。
标签: delphi delphi-xe6 datasnap