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

FireDAC Append函数未创建新记录反而修改已有记录求助

问题排查:C++Builder 12下FireDAC+SQLite的Append()异常问题

问题背景

使用C++Builder 12开发Windows平台的简易CRUD应用,采用SQLite数据库与FireDAC组件。应用包含两个主菜单,其中第二个主菜单存在异常:

  • 点击“nouvelle rallonge”(新延长件)或“nouveau tube”(新管件)按钮时,调用对应窗口执行Append()+Post()操作
  • 预期行为:创建新数据库记录
  • 实际异常:未生成新条目,反而修改DBGrid中显示的现有记录
  • 其他页面采用相同窗口架构(基于TDBEdit)和代码逻辑,运行完全正常

相关代码

第二主页面代码

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "menuApp.h"
#include "menuRallonges.h"
#include "datamodule.h"
#include "gestionRallonge.h"
#include "gestionTube.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFMenuRallonges *FMenuRallonges;
extern bool isEditing;
//---------------------------------------------------------------------------
__fastcall TFMenuRallonges::TFMenuRallonges(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TFMenuRallonges::btRallongeClick(TObject *Sender)
{
    TFRallonge *FRallonge = new TFRallonge(this);
    short res = FRallonge->ShowModal();
    delete FRallonge;

}
//---------------------------------------------------------------------------
void __fastcall TFMenuRallonges::btTubeClick(TObject *Sender)
{
    TFTube *FTube = new TFTube(this);
    short res = FTube->ShowModal();
    delete FTube;

}
//---------------------------------------------------------------------------

void __fastcall TFMenuRallonges::FormShow(TObject *Sender)
{
   DataModule1 = new TDataModule1(this);
    isEditing=false;
    DBGrid1->DataSource->DataSet->Refresh();
    DBGrid2->DataSource->DataSet->Refresh();
}
//---------------------------------------------------------------------------

void __fastcall TFMenuRallonges::btModifRallongeClick(TObject *Sender)
{
   isEditing=true;
   btRallongeClick(this);
   FormShow(this);
}
//---------------------------------------------------------------------------

void __fastcall TFMenuRallonges::btModifTubeClick(TObject *Sender)
{
   isEditing=true;
   btTubeClick(this);
    FormShow(this);
}
//---------------------------------------------------------------------------


void __fastcall TFMenuRallonges::FormDestroy(TObject *Sender)
{
    if (DataModule1 != nullptr)
    {
        delete DataModule1;
        DataModule1 = nullptr;
    }
}
//---------------------------------------------------------------------------

void __fastcall TFMenuRallonges::FormClose(TObject *Sender, TCloseAction &Action)
{
    FormDestroy(this);
}
//---------------------------------------------------------------------------

管件页面代码

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "datamodule.h"
#include "menuRallonges.h"
#include "gestionTube.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFTube *FTube;
extern bool isEditing;
//---------------------------------------------------------------------------
__fastcall TFTube::TFTube(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TFTube::Button1Click(TObject *Sender)
{
    Button1->SetFocus();
    try {
        DataModule1->TubevideTable->Post();
    }
    catch (const Exception &E) {
        ShowMessage("Erreur lors de l'insertion : " + E.Message);
    }
}
//---------------------------------------------------------------------------

void __fastcall TFTube::FormShow(TObject *Sender)
{

    if (isEditing==true) {
//      ShowMessage("editing true");
    }
    else
    {
//      ShowMessage("editing false");
//      DataModule1->TubevideTable->Last();
        DataModule1->TubevideTable->Append();

    }

}
//---------------------------------------------------------------------------
void __fastcall TFTube::Button2Click(TObject *Sender)
{
    DataModule1->TubevideTable->Cancel();
}
//---------------------------------------------------------------------------

问题原因排查及修复建议

1. DataModule重复创建导致数据集实例冲突

第二主页面的FormShow方法中,每次页面显示都会新建DataModule1实例:

DataModule1 = new TDataModule1(this);

这会导致:

  • 当前操作的数据集(管件/延长件窗口中调用的)是新DataModule的实例
  • DBGrid绑定的是旧DataModule的数据集实例
  • 视觉上看到“修改现有记录”,实际是新数据集默认指向第一条记录并进入编辑状态,而DBGrid未同步新数据集的内容

修复:

  • 改为在应用启动时初始化全局DataModule,避免重复创建
  • 或确保所有页面共享同一个DataModule实例,不在FormShow中重复实例化

2. 全局变量isEditing的竞态问题

修改按钮点击后,先设置isEditing=true,调用窗口后立即执行FormShow重置isEditing=false,可能导致管件窗口的FormShow执行时,isEditing已经被重置为false,逻辑判断出错。

修复:

  • 移除全局变量isEditing,改为通过窗口构造函数传递参数的方式传递编辑状态:
    // 修改管件窗口的构造函数
    class TFTube : public TForm
    {
    private:
        bool fIsEditing;
    public:
        __fastcall TFTube(TComponent* Owner, bool editing);
        // ...
    };
    
    __fastcall TFTube::TFTube(TComponent* Owner, bool editing)
        : TForm(Owner), fIsEditing(editing)
    {
    }
    
    // 调用窗口时传递参数
    void __fastcall TFMenuRallonges::btTubeClick(TObject *Sender)
    {
        bool editing = (Sender == btModifTube); // 根据按钮判断编辑状态
        TFTube *FTube = new TFTube(this, editing);
        short res = FTube->ShowModal();
        delete FTube;
    }
    

3. 数据集状态未正确重置

执行Append()前,若数据集处于编辑状态(比如之前未提交的修改),Append()可能不会创建新记录,而是继续编辑当前记录。

修复:
在Append()前添加状态检查,确保数据集处于浏览状态:

void __fastcall TFTube::FormShow(TObject *Sender)
{
    if (fIsEditing) {
        // 编辑逻辑
    }
    else
    {
        if (DataModule1->TubevideTable->State != dsBrowse)
            DataModule1->TubevideTable->Cancel();
        DataModule1->TubevideTable->Append();
    }
}

4. DBGrid与数据集的绑定验证

检查第二主页面的DBGrid的DataSource是否正确绑定到DataModule的对应数据集,重复创建DataModule会导致绑定失效,DBGrid显示旧数据,造成操作错觉。

验证:
在FormShow中添加代码,确认DBGrid绑定的数据集与操作的数据集是同一个实例:

ShowMessage(DBGrid2->DataSource->DataSet->Name == DataModule1->TubevideTable->Name ? "绑定正确" : "绑定异常");

内容的提问来源于stack exchange,提问作者Alan Finiti

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 19:04:56