You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dataset未处于编辑/插入模式错误:数据库数据加载问题求助

问题描述

我是Stack Overflow新用户,目前在推进一个大型项目,向数据库加载数据时反复遇到**"Dataset not in edit or insert mode"**错误。我已经标记了必要变量,尝试在循环内外、case语句中使用tbl().Edit和tbl().Insert,但问题依旧。

全局变量包括sPlayer1、sPlayer2、iScore1、iScore2,相关代码如下:

procedure TfrmInvigilator.btnSubmitClick(Sender: TObject);
Var
  i, j, iRound: Integer;
begin
  sPlayer1 := cmbName1.Text; // Assigning values to variables for cmbPlayers
  sPlayer2 := cmbName2.Text;

  iScore1 := sedScore1.Value; // Assigning values to variables for sedScores
  iScore2 := sedScore2.Value;

  iRound := cmbRound.ItemIndex; // Assigning values to variable for cmbRound

  if (cmbName1.ItemIndex = -1) then
  // Displays show message if cbmName1 is blank
  begin
    ShowMessage('Please select player name');
  end
  else
  begin // If cbmName1 is not blank then:
    i := pos(' ', sPlayer1); // Find position of ' ' in cbmName1.Text
    sPlayer1 := Copy(sPlayer1, 1, i - 1); // sPlayer1 := Name of player

    dmChess.tblPlayerInfo.Locate('Name', sPlayer1, []); // Locates Name in table
    Num1 := dmChess.tblPlayerInfo['ID']; // Retrives ID of player

    with dmChess do
    begin
      tblScoreboard.First;

      while NOT tblScoreboard.EOF do
      begin
        tblScoreboard.Locate('ID', Num1, []);

        case iRound of
          0:
              tblScoreboard['Round 1A'] := iScore1;
          1:
              tblScoreboard['Round 1B'] := iScore1;
          2:
              tblScoreboard['Round 1C'] := iScore1;
          3:
              tblScoreboard['Round 1D'] := iScore1;
          4:
              tblScoreboard['Round 2'] := iScore1;
          5:
              tblScoreboard['Semi-Final'] := iScore1;
          6:
              tblScoreboard['Final'] := iScore1;
        end;

        tblScoreboard.Post;
      end;
    end;
  end;

   if (cmbName2.ItemIndex = -1) then
   // Displays show message if cbmName2 is blank
   begin
   ShowMessage('Please slecet player name');
   end
   else
   begin // If cbmName2 is not blank then:
   j := pos(' ', sPlayer2); // Find position of ' ' in cbmName2.Text
   sPlayer2 := Copy(sPlayer2, 1, j - 1); // sPlayer2 := Name of player

   dmChess.tblPlayerInfo.Locate('Name', sPlayer2, []); // Locates Name in table
   Num1 := dmChess.tblPlayerInfo['ID']; // Retrives ID of player
   end;

end;
问题分析与修复方案

核心问题

  1. 未进入编辑模式就修改字段:直接赋值tblScoreboard['Round XX'] := iScore1前,没有调用tblScoreboard.Edit,数据集默认处于浏览模式,不允许修改。
  2. 循环逻辑冗余且错误:while NOT tblScoreboard.EOF do循环会遍历整个表,但每次循环里又用Locate定位到目标记录,导致无限循环(Locate不会移动EOF状态),同时多次重复操作同一记录。
  3. 未处理Locate失败的情况:如果找不到对应ID的记录,后续修改会报错。
  4. Player2的逻辑未完成:Player2的ID获取后没有更新分数的代码。

修复后的代码

procedure TfrmInvigilator.btnSubmitClick(Sender: TObject);
Var
  i, j, iRound: Integer;
  bFound: Boolean;
begin
  sPlayer1 := cmbName1.Text;
  sPlayer2 := cmbName2.Text;

  iScore1 := sedScore1.Value;
  iScore2 := sedScore2.Value;

  iRound := cmbRound.ItemIndex;

  // 处理Player1
  if (cmbName1.ItemIndex = -1) then
  begin
    ShowMessage('请选择玩家1的姓名');
  end
  else
  begin
    i := pos(' ', sPlayer1);
    if i > 0 then
      sPlayer1 := Copy(sPlayer1, 1, i - 1);

    // 查找Player1的ID,处理查找失败的情况
    bFound := dmChess.tblPlayerInfo.Locate('Name', sPlayer1, []);
    if not bFound then
    begin
      ShowMessage('未找到玩家:' + sPlayer1);
      Exit;
    end;
    Num1 := dmChess.tblPlayerInfo['ID'];

    with dmChess.tblScoreboard do
    begin
      // 定位到目标记录,避免遍历整个表
      bFound := Locate('ID', Num1, []);
      if not bFound then
      begin
        ShowMessage('玩家' + sPlayer1 + '未在积分榜中找到');
        Exit;
      end;

      // 进入编辑模式
      Edit;
      case iRound of
        0: FieldByName('Round 1A').AsInteger := iScore1;
        1: FieldByName('Round 1B').AsInteger := iScore1;
        2: FieldByName('Round 1C').AsInteger := iScore1;
        3: FieldByName('Round 1D').AsInteger := iScore1;
        4: FieldByName('Round 2').AsInteger := iScore1;
        5: FieldByName('Semi-Final').AsInteger := iScore1;
        6: FieldByName('Final').AsInteger := iScore1;
      end;
      // 提交修改
      Post;
    end;
  end;

  // 处理Player2
  if (cmbName2.ItemIndex = -1) then
  begin
    ShowMessage('请选择玩家2的姓名');
  end
  else
  begin
    j := pos(' ', sPlayer2);
    if j > 0 then
      sPlayer2 := Copy(sPlayer2, 1, j - 1);

    bFound := dmChess.tblPlayerInfo.Locate('Name', sPlayer2, []);
    if not bFound then
    begin
      ShowMessage('未找到玩家:' + sPlayer2);
      Exit;
    end;
    Num1 := dmChess.tblPlayerInfo['ID'];

    with dmChess.tblScoreboard do
    begin
      bFound := Locate('ID', Num1, []);
      if not bFound then
      begin
        ShowMessage('玩家' + sPlayer2 + '未在积分榜中找到');
        Exit;
      end;

      Edit;
      case iRound of
        0: FieldByName('Round 1A').AsInteger := iScore2;
        1: FieldByName('Round 1B').AsInteger := iScore2;
        2: FieldByName('Round 1C').AsInteger := iScore2;
        3: FieldByName('Round 1D').AsInteger := iScore2;
        4: FieldByName('Round 2').AsInteger := iScore2;
        5: FieldByName('Semi-Final').AsInteger := iScore2;
        6: FieldByName('Final').AsInteger := iScore2;
      end;
      Post;
    end;
  end;
end;

关键修复点

  • 每次修改记录前必须调用Edit,确保数据集进入编辑模式。
  • 去掉冗余的while循环,直接用Locate定位目标记录,避免无限循环和无效遍历。
  • 添加Locate结果判断,处理记录不存在的异常情况。
  • 补全Player2的分数更新逻辑,和Player1保持一致。
  • 使用FieldByName('字段名').AsInteger替代直接数组访问,代码更健壮且可读性更高。
  • 把提示信息改为中文,符合使用场景。

内容的提问来源于stack exchange,提问作者Iman Amien

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 06:05:24