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;
问题分析与修复方案
核心问题
- 未进入编辑模式就修改字段:直接赋值
tblScoreboard['Round XX'] := iScore1前,没有调用tblScoreboard.Edit,数据集默认处于浏览模式,不允许修改。 - 循环逻辑冗余且错误:
while NOT tblScoreboard.EOF do循环会遍历整个表,但每次循环里又用Locate定位到目标记录,导致无限循环(Locate不会移动EOF状态),同时多次重复操作同一记录。 - 未处理
Locate失败的情况:如果找不到对应ID的记录,后续修改会报错。 - 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
相关产品推荐
相关产品推荐

