在 delphi Xe8 中将数据插入数据库

Inserting data into a database in delphi Xe8

我正在处理的项目需要一个需要将用户详细信息插入数据库的注册表单 table。

问题是单击“注册”按钮时,输入到编辑中的数据不会保存或更新到数据库中。我还遇到访问冲突 "access violation at 0x0065e3e9 read of address 0x0000006c",并且我的代码在 "tblUsers.Insert".

中断

我已经测试了我的代码,并使用 Breaks 遍历了每一行代码以找到问题的根源,我发现它是以下代码部分。

with dmSM do
  begin
    tblUsers.Insert;
    tblUsers['FirstName'] := edtFirstName.Text;
    tblUsers['LastName'] := edtLastName.Text;
    tblUsers['BirthDate'] := cmbDay.Text + ' ' + cmbMonth.Text + ' ' +
                             cmbYear.Text;
    tblUsers['Gender'] := cmbGender.Text;
    tblUsers['AccountName'] := edtAccountName.Text;
    tblUsers['Password'] := edtPassword.Text;
    tblUsers.Post;
end; //end of with

我会尝试另一种方法,但如果我能得到一些帮助,这将很有帮助。

提前致谢

多米尼克

为了完整起见以及为了未来读者的利益,我把这个答案放上去。

在您的情况下,首先要做的是在 btlUsers.Insert 上放置一个断点。这将确认执行到那个点并且当该行执行时发生异常。

为什么异常?消息部分有一条线索,上面写着 "read of address 0x0000006c"。在 Delphi 中,一个 Nil 指针实际上是 0x00000000,而 6c 是一个小数字(十进制为 108),这就是线索,调试器告诉您异常发生在距 0x00000000 的一个小偏移处。

编译后的Delphi代码的一个特点是对象的数据字段等成员的地址是固定的(通常相当小,除非所讨论的class是非常大)从对象的基址偏移。

在你的例子中,6c 偏移量是从 0x00000000 开始的,因此,一个合理的解释是你的代码试图读取一个实际上是 Nil 的对象的成员。

因此,在断点处计算 dmSM 和 tblUsers。调试器告诉您 dmSM 为 Nil 并且 tblUsers 不可访问,并且它不可访问因为 dmSM 为 Nil。为什么 dmSM 为零?

很可能是因为它是一个引用到达断点时尚未创建的对象的变量。所以:

转到项目管理器,右键单击其中的可执行文件和 select 选项。左侧树中的表单条目会告诉您哪些 forms/datamodules 具有与其关联的自动创建的变量以及它们的创建顺序。

然后,查看.Dpr 文件。它应该看起来像这样:

begin
  Application.Initialize;
  Application.CreateForm(TDataModule1, DataModule1);
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

如果它缺少创建数据模块的行,或者它出现在创建表单的行之后,那是你的问题,修复起来很简单。

但是,有时,.Dpr 文件中似乎一切正常,但仍然会出现异常。 @JerryDodge 提出了这一点,这是一个很好的观点。发生的情况是(通常是由于编辑错误),您复制了一个自动创建的对象的声明。因此,现在,例如,您声明了两个 dmSM,一个在定义 TdmSM 的单元中,另一个在编译器在编译过程中看到的其他地方 after 中的一个在您的数据模块中单元。因为它最近在编译发生异常的单元时看到了重复项,所以它假定您的代码引用的是重复项,而不是原始代码。

我试图以如此尖锐的细节回答这个问题的原因是要说明很多调试过程正在思考你从仔细观察(并在 SO q 中报告)中获得的线索你的错误程序的行为。

最后,避免使用"with"。虽然它可能会为您节省一些打字时间,但在较长的 运行 中,它往往会造成比其价值更多的麻烦。在您的表单单元中,如果您需要继续引用数据模块中的某个对象,请将其值分配给本地范围内的变量,以您正在执行的表单中的过程,或者(更好)定义一个函数returns有问题的对象,像这样

function TForm1.tblUsers : TDataSet;
begin
  Result := dmSM.tblUsers;
end;