【问题标题】:Not able to access Field Values with a Dataset's FieldByName Method [closed]无法使用数据集的 FieldByName 方法访问字段值 [关闭]
【发布时间】:2021-04-27 08:27:42
【问题描述】:

我有字段值数据集'EmployeeID',其值为'007' 我想将它分配给一个字符串变量'EmployeeID',这是由下面的代码完成的,值被成功复制到'EmployeeID'变量,但我不能将变量 EmployeeID 的值分配给数据集。请帮帮我。

String EmployeeID = Customers->FieldByName("EmployeeID")->AsString;
// Above line is working fine. Currently dataset field value is '007'

Customers->FieldByName("EmployeeID")->AsString = "";

现在我重新为数据集赋值,它仍然打印 null。

Customers->FieldByName("EmployeeID")->AsString = EmployeeID;

为什么。我想要数据集中的值再次为 007。我该怎么做?

【问题讨论】:

  • 你的问题是 C++ Builder,删除标签 Delphi。
  • 完成了,您能帮我完成上述查询吗? @fpiette
  • 也许如果您提供一个完整的最小可重现示例来显示您的问题。最低限度意味着严格的最低限度,但完整地证明了您的问题。然后,我将能够快速检查,而无需先尝试自己重现您的问题。遵循本指南:stackoverflow.com/help/minimal-reproducible-example
  • Customers->FieldByName("EmployeeID")->AsString 的值为 '007' String EmployeeID = Customers->FieldByName("EmployeeID")->AsString; //为新的字符串变量赋值。现在 EmployeeID 的值为 007。 Customers->FieldByName("EmployeeID")->AsString = "" //从数据集中清除值。客户->FieldByName("EmployeeID")->AsString = EmployeeID; //将值重新分配给007,但仍然从数据集中获得空值。为什么?你现在能帮帮我吗?我想现在很清楚了。 @fpiette
  • minimal reproducible example 不仅仅是评论中包含的一小段代码。它应该被编辑到您的 q 中(尽管在另一条评论中已经说过)并且应该是独立的,换句话说,读者应该可以复制和粘贴它,然后编译并运行它,以便他们可以重现自己系统的问题。我已经投票决定关闭这个 q,直到你这样做。

标签: c++ delphi c++builder


【解决方案1】:

由于您最初标记了您的 q Delphi 并且数据集组件是用 Delphi 编写的,因此我发布了一个 Delphi 对您的 q 的回答。

创建一个新的控制台项目并将以下代码粘贴到其中:

program DatasetEdit;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, Data.DB, DataSnap.DBClient;

var
  CDS : TClientDataSet;
  AField : TField;
  S : String;

begin
  try
    //  Create dataset and fields
    CDS := TClientDataSet.Create(Nil);

    AField := TIntegerField.Create(CDS);
    AField.FieldName := 'RecordID';
    AField.DataSet := CDS;

    AField := TStringField.Create(CDS);
    AField.FieldName := 'EmployeeID';
    AField.Size := 8;
    AField.DataSet := CDS;

    CDS.CreateDataSet;

    //  insert single record
    CDS.InsertRecord([1, '007']);

    S := CDS.FieldByName('EmployeeID').AsString;
    writeln('S = ', S);

    //  attempt to change EmployeeID field
{.$define UseEdit'}
{$ifdef UseEdit}
    CDS.Edit;
{$endif}
    //  expect an exception here if `UsedEdit` is undefined
    CDS.FieldByName('EmployeeID').AsString := '';

    writeln('EmploeyeeID is now ', CDS.FieldByName('EmployeeID').AsString);

    CDS.FieldByName('EmployeeID').AsString := S;

    writeln('EmploeyeeID is now ', CDS.FieldByName('EmployeeID').AsString);

    //  don't leave CDS in dsEdit state
    CDS.Cancel;

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  writeln('Press any key');
  readln;
end.

编译代码,然后在调试器中单步执行。您应该在分配给CDS.FieldByName('EmployeeID').AsString 时获得例外。


调试器异常通知

Project DatasetEdit.exe 引发异常类 EDatabaseError,并显示消息“数据集未处于编辑或插入模式”。

然后,从{.$define UseEdit'} 中删除点,重新编译并重复该过程。这一次,代码应该正确执行并产生预期的结果,最终恢复CDS.FieldByName('EmployeeID').AsString的保存值。

这种行为差异的原因是所有具体的 TDataSet 后代所基于的 TDataSet 类严格实现了一个状态机(其状态反映在数据集的 State 属性中),它确保数据集对于正在进行的任何操作,都处于正确的状态。

在 Data.DB 中,TDataSetState 定义为

  TDataSetState = (dsInactive, dsBrowse, dsEdit, dsInsert, dsSetKey,
    dsCalcFields, dsFilter, dsNewValue, dsOldValue, dsCurValue, dsBlockRead,
    dsInternalCalc, dsOpening)

除其他外,此状态机要求数据集处于dsEditdsInsert 状态以允许更改字段内容。数据集通过分别调用EditInsert 进入这些状态。数据集的导航,例如仅当数据集处于 dsBrowse 状态时才允许通过调用 FirstNextLast 等。

【讨论】:

  • 嗯,这对您解决问题有帮助吗?
猜你喜欢
  • 2017-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-31
  • 1970-01-01
相关资源
最近更新 更多