Delphi - ADOTable 没有正确删除记录并创建了幻影记录
Delphi - ADOTable does not delete records properly and creates ghost records
我需要帮助解决我的数据库问题。我有一个包含汽车记录的 .mdb 文件。这链接到我的 ADOTable,然后链接到 Delphi 中的 DBGrid。当我通过表单上的按钮删除记录时,它似乎没有正确删除它,因为当我滚动 dbgrid 时,活动记录假设为 change/update (取决于我是向下还是向上滚动) 并在 DBGrid 下面的编辑中显示活动记录的每个字段的值。
在我的代码删除记录后,当我在 MS Access 中查看它时,它没有出现在 DBGrid 或 .mdb 文件中,所以我认为它已被正确删除。但是,就像我上面解释的那样,当 OnMouseWheel 事件执行时,它会显示我猜是删除的记录,或者以前记录的数据DBGrid 活动记录的指针清楚地表明它应该显示下一条或上一条记录数据。
有趣的是,OnCellClick 和 DBGridNavigator 按钮对 DBGrid 和显示的记录信息没有这种影响。
图片:
在 OnMouseWheel 事件之前
每张图片执行1次后:
实际 .mdb 文件的图像:
使用的过程和函数代码:
OnMouseWheel:
procedure TCars.DBGrid1MouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer;
MousePos: TPoint; var Handled: Boolean);
begin
Show_Car_Details;
end;
OnCellClick:
procedure TCars.DBGrid1CellClick(Column: TColumn);
begin
Show_Car_Details;
end;
Show_Car_Details:
procedure TCars.Show_Car_Details;
begin
with CarOwners.tbl_Cars do
begin
edt_Car_ID.text := inttostr(fieldbyname('ID').value);
edt_Car_Type.text := fieldbyname('Make').value;
edt_Car_Price.text := FloatToStr(fieldbyname('Price').value);
edt_Car_Distance.text := inttostr(fieldbyname('Distance').value);
edt_Owner_ID.text := inttostr(fieldbyname('OwnerID').value);
if fieldbyname('Insurance').value = true then
begin
cbx_Insurance.ItemIndex := 0;
end
else
begin
cbx_Insurance.ItemIndex := 1;
end;
end;
end;
删除程序:
procedure TCars.bit_DeleteClick(Sender: TObject);
begin
if messagedlg
('Are you sure you want to delete this record? It will permanently be removed.',
mtConfirmation, [mbyes, mbno], 0) <> mryes then
exit;
CarOwners.tbl_Cars.Delete;
DBGrid1.DataSource.DataSet.Refresh;
end;
以防万一,添加和更新程序的代码:
添加:
procedure TCars.bit_AddClick(Sender: TObject);
var
Make: string;
OwnerID, Distance: Integer;
Price: real;
Insurance: Boolean;
begin
Make := edt_Car_Type.text;
OwnerID := strtoint(edt_Owner_ID.text);
Distance := strtoint(edt_Car_Distance.text);
Price := strtofloat(edt_Car_Price.text);
if cbx_Insurance.ItemIndex = 0 then
begin
Insurance := true;
end
else
begin
Insurance := false;
end;
Add_Record(Make, OwnerID, Price, Distance, Insurance);
end;
//---------------------------------------------------------
procedure TCars.Add_Record(Make: string; OwnerID: Integer; Price: real;
Distance: Integer; Insurance: Boolean);
begin
// ----validation----
//validation done here(removed for space, just basic if with exit.)
// add new information
with CarOwners do
begin
tbl_Cars.DisableControls;
tbl_Cars.last;
tbl_Cars.Insert;
tbl_Cars['Make'] := Make;
tbl_Cars['OwnerID'] := OwnerID;
tbl_Cars['Price'] := Price;
tbl_Cars['distance'] := Distance;
tbl_Cars['Insurance'] := Insurance;
tbl_Cars.post;
tbl_Cars.EnableControls;
end;
end;
更新程序:
procedure TCars.bit_UpdateClick(Sender: TObject);
var
Brand: string;
Price: real;
Insurance: Boolean;
OwnerID, Distance: Integer;
begin
Brand := edt_Car_Type.text;
Price := strtofloat(edt_Car_Price.text);
OwnerID := strtoint(edt_Owner_ID.text);
Distance := strtoint(edt_Car_Distance.text);
if cbx_Insurance.ItemIndex = 0 then
begin
Insurance := true;
end
else
begin
Insurance := false;
end;
Update_Record(Brand, OwnerID, Price, Distance, Insurance);
end;
//------------------------------------------------------------
procedure TCars.Update_Record(Make: string; OwnerID: Integer; Price: real;
Distance: Integer; Insurance: Boolean);
begin
//validation done here(removed for space, just basic if with exit.)
// ----Update Information ----
with CarOwners do
begin
tbl_Cars.DisableControls;
tbl_Cars.edit;
tbl_Cars['Make'] := Make;
tbl_Cars['OwnerID'] := OwnerID;
tbl_Cars['Price'] := Price;
tbl_Cars['Distance'] := Distance;
if Insurance then
begin
tbl_Cars['Insurance'] := true;
end
else
begin
tbl_Cars['Insurance'] := false;
end;
// ShowMessage('Posting...');
tbl_Cars.post;
// ShowMessage('Done');
tbl_Cars.EnableControls;
end;
end;
欢迎任何建议或帮助!!!
此致
感谢@MartynA 和@Olivier 的回答。问题是使用了错误的事件处理程序来刷新和显示记录的字段值。
请勿使用:
OnMouseWheel
使用:
procedure TCarOwners.ds_CarsDataChange(Sender: TObject; Field: TField);
begin
if Field = nil then
begin
Cars.show_car_details;
end;
end;
这会正确更新非 data-aware 控件。请务必将 Form1
或我的 Cars_frm
添加到 implementation
下的 uses
列表中。
我需要帮助解决我的数据库问题。我有一个包含汽车记录的 .mdb 文件。这链接到我的 ADOTable,然后链接到 Delphi 中的 DBGrid。当我通过表单上的按钮删除记录时,它似乎没有正确删除它,因为当我滚动 dbgrid 时,活动记录假设为 change/update (取决于我是向下还是向上滚动) 并在 DBGrid 下面的编辑中显示活动记录的每个字段的值。
在我的代码删除记录后,当我在 MS Access 中查看它时,它没有出现在 DBGrid 或 .mdb 文件中,所以我认为它已被正确删除。但是,就像我上面解释的那样,当 OnMouseWheel 事件执行时,它会显示我猜是删除的记录,或者以前记录的数据DBGrid 活动记录的指针清楚地表明它应该显示下一条或上一条记录数据。
有趣的是,OnCellClick 和 DBGridNavigator 按钮对 DBGrid 和显示的记录信息没有这种影响。
图片:
在 OnMouseWheel 事件之前
每张图片执行1次后:
使用的过程和函数代码:
OnMouseWheel:
procedure TCars.DBGrid1MouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer;
MousePos: TPoint; var Handled: Boolean);
begin
Show_Car_Details;
end;
OnCellClick:
procedure TCars.DBGrid1CellClick(Column: TColumn);
begin
Show_Car_Details;
end;
Show_Car_Details:
procedure TCars.Show_Car_Details;
begin
with CarOwners.tbl_Cars do
begin
edt_Car_ID.text := inttostr(fieldbyname('ID').value);
edt_Car_Type.text := fieldbyname('Make').value;
edt_Car_Price.text := FloatToStr(fieldbyname('Price').value);
edt_Car_Distance.text := inttostr(fieldbyname('Distance').value);
edt_Owner_ID.text := inttostr(fieldbyname('OwnerID').value);
if fieldbyname('Insurance').value = true then
begin
cbx_Insurance.ItemIndex := 0;
end
else
begin
cbx_Insurance.ItemIndex := 1;
end;
end;
end;
删除程序:
procedure TCars.bit_DeleteClick(Sender: TObject);
begin
if messagedlg
('Are you sure you want to delete this record? It will permanently be removed.',
mtConfirmation, [mbyes, mbno], 0) <> mryes then
exit;
CarOwners.tbl_Cars.Delete;
DBGrid1.DataSource.DataSet.Refresh;
end;
以防万一,添加和更新程序的代码: 添加:
procedure TCars.bit_AddClick(Sender: TObject);
var
Make: string;
OwnerID, Distance: Integer;
Price: real;
Insurance: Boolean;
begin
Make := edt_Car_Type.text;
OwnerID := strtoint(edt_Owner_ID.text);
Distance := strtoint(edt_Car_Distance.text);
Price := strtofloat(edt_Car_Price.text);
if cbx_Insurance.ItemIndex = 0 then
begin
Insurance := true;
end
else
begin
Insurance := false;
end;
Add_Record(Make, OwnerID, Price, Distance, Insurance);
end;
//---------------------------------------------------------
procedure TCars.Add_Record(Make: string; OwnerID: Integer; Price: real;
Distance: Integer; Insurance: Boolean);
begin
// ----validation----
//validation done here(removed for space, just basic if with exit.)
// add new information
with CarOwners do
begin
tbl_Cars.DisableControls;
tbl_Cars.last;
tbl_Cars.Insert;
tbl_Cars['Make'] := Make;
tbl_Cars['OwnerID'] := OwnerID;
tbl_Cars['Price'] := Price;
tbl_Cars['distance'] := Distance;
tbl_Cars['Insurance'] := Insurance;
tbl_Cars.post;
tbl_Cars.EnableControls;
end;
end;
更新程序:
procedure TCars.bit_UpdateClick(Sender: TObject);
var
Brand: string;
Price: real;
Insurance: Boolean;
OwnerID, Distance: Integer;
begin
Brand := edt_Car_Type.text;
Price := strtofloat(edt_Car_Price.text);
OwnerID := strtoint(edt_Owner_ID.text);
Distance := strtoint(edt_Car_Distance.text);
if cbx_Insurance.ItemIndex = 0 then
begin
Insurance := true;
end
else
begin
Insurance := false;
end;
Update_Record(Brand, OwnerID, Price, Distance, Insurance);
end;
//------------------------------------------------------------
procedure TCars.Update_Record(Make: string; OwnerID: Integer; Price: real;
Distance: Integer; Insurance: Boolean);
begin
//validation done here(removed for space, just basic if with exit.)
// ----Update Information ----
with CarOwners do
begin
tbl_Cars.DisableControls;
tbl_Cars.edit;
tbl_Cars['Make'] := Make;
tbl_Cars['OwnerID'] := OwnerID;
tbl_Cars['Price'] := Price;
tbl_Cars['Distance'] := Distance;
if Insurance then
begin
tbl_Cars['Insurance'] := true;
end
else
begin
tbl_Cars['Insurance'] := false;
end;
// ShowMessage('Posting...');
tbl_Cars.post;
// ShowMessage('Done');
tbl_Cars.EnableControls;
end;
end;
欢迎任何建议或帮助!!! 此致
感谢@MartynA 和@Olivier 的回答。问题是使用了错误的事件处理程序来刷新和显示记录的字段值。
请勿使用:
OnMouseWheel
使用:
procedure TCarOwners.ds_CarsDataChange(Sender: TObject; Field: TField);
begin
if Field = nil then
begin
Cars.show_car_details;
end;
end;
这会正确更新非 data-aware 控件。请务必将 Form1
或我的 Cars_frm
添加到 implementation
下的 uses
列表中。