你并没有开启事务,数据当然提交进去了,你只不过开启了ADOQUERY的缓存功能; if not ADOCONNECTIONG.InTransaction then dm.adoc.BeginTrans ; Try 主表.UpdateBatch(arAll); 子表.UpdateBatch(arAll); ADOCONNECTIONG.CommitTrans; except ADOCONNECTIONG.RollbackTrans;//存盘失败! end;
顺便问一句:三层系统中,可以使用ADOCONNECTIONG的事务吗?
问题是,你真的设置好了ADO的缓冲了吗?要让ADO缓冲起来,必须设置下面的属性: with TADODataSet do begin CursorLocation := clUseClient; CursorType := ctStatic; LockType := ltBatchOptimistic; CommandType := cmdText; CommandText := 'SELECT * FROM Employee'; Open; end; 此后,你可以对数据进行操作,操作完成之后,可以使用UpdateBatch和CancelBatch。
具体的,请参看Delphi的帮助系统:Using batch updates
kingron你以前不是不搞DB的吗?
使用缓存更新试试!cached updates 。When you apply updates for master/detail tables, the order in which you list datasets to update is significant. Generally you should always update master tables before detail tables, except when handling deleted records. In complex master/detail relationships where the detail table for one relationship is the master table for another detail table, the same rule applies. You can update master/detail tables at the database or dataset component levels. For purposes of control (and of creating explicitly self-documented code), you should apply updates at the dataset level. The following example illustrates how you should code cached updates to two tables, Master and Detail, involved in a master/detail relationship:Database1.StartTransaction;try Master.ApplyUpdates; Detail.ApplyUpdates; Database1.Commit; except Database1.Rollback; raise; end; Master.CommitUpdates; Detail.CommitUpdates;If an error occurs during the application of updates, this code also leaves both the cache and the underlying data in the database tables in the same state they were in before the calls to ApplyUpdates. If an exception is raised during the call to Master.ApplyUpdates, it is handled like the single dataset case previously described. Suppose, however, that the call to Master.ApplyUpdates succeeds, and the subsequent call to Detail.ApplyUpdates fails. In this case, the changes are already applied to the master table. Because all data is updated inside a database transaction, however, even the changes to the master table are rolled back when Database1.Rollback is called in the except block. Furthermore, UpdatesMaster.CommitUpdates is not called because the exception which is re-raised causes that code to be skipped, so the cache is also left in the state it was before the attempt to update.To appreciate the value of the two-phase update process, assume for a moment that ApplyUpdates is a single-phase process which updates the data and the cache. If this were the case, and if there were an error while applying the updates to the Detail table, then there would be no way to restore both the data and the cache to their original states. Even though the call to Database1.Rollback would restore the database, there would be no way to restore the cache.
1、主表不做缓存更新,而从表做。 2、用TADOQuery,但不连接主从表关系。 从表的SQL内容是:SELECT * FROM 从表 WHERE 连接字段名=:查询参数名(当然,你也可以不加条件,而用Filter来进行) 在主表的afterScroll事件中写代码,当主表记录指针移动时,设从表查询参数值为主表的与从表的连接字段值,并Requery。而当从表新增记录时,手工给从表对应的连接字段赋值。
记住:对数据库的所有操作最好用SQL语句实现,不要用delphi中query\table\等提供的如:table.insert\query.append等一类,能气死你,delphi在这方面做的太差了。但如果全部用SQL语句,就太简单了。最多加一个事务处理。
OK,回去解决了吧。看来今天不用加班了。回家陪女朋友吧。
一两句说不清楚,你给我个邮箱,我给你发过去。
if not ADOCONNECTIONG.InTransaction then dm.adoc.BeginTrans ;
Try
主表.UpdateBatch(arAll);
子表.UpdateBatch(arAll);
ADOCONNECTIONG.CommitTrans;
except
ADOCONNECTIONG.RollbackTrans;//存盘失败!
end;
with TADODataSet do begin
CursorLocation := clUseClient;
CursorType := ctStatic;
LockType := ltBatchOptimistic;
CommandType := cmdText;
CommandText := 'SELECT * FROM Employee';
Open;
end;
此后,你可以对数据进行操作,操作完成之后,可以使用UpdateBatch和CancelBatch。
You can update master/detail tables at the database or dataset component levels. For purposes of control (and of creating explicitly self-documented code), you should apply updates at the dataset level. The following example illustrates how you should code cached updates to two tables, Master and Detail, involved in a master/detail relationship:Database1.StartTransaction;try
Master.ApplyUpdates;
Detail.ApplyUpdates;
Database1.Commit;
except
Database1.Rollback;
raise;
end;
Master.CommitUpdates;
Detail.CommitUpdates;If an error occurs during the application of updates, this code also leaves both the cache and the underlying data in the database tables in the same state they were in before the calls to ApplyUpdates.
If an exception is raised during the call to Master.ApplyUpdates, it is handled like the single dataset case previously described. Suppose, however, that the call to Master.ApplyUpdates succeeds, and the subsequent call to Detail.ApplyUpdates fails. In this case, the changes are already applied to the master table. Because all data is updated inside a database transaction, however, even the changes to the master table are rolled back when Database1.Rollback is called in the except block. Furthermore, UpdatesMaster.CommitUpdates is not called because the exception which is re-raised causes that code to be skipped, so the cache is also left in the state it was before the attempt to update.To appreciate the value of the two-phase update process, assume for a moment that ApplyUpdates is a single-phase process which updates the data and the cache. If this were the case, and if there were an error while applying the updates to the Detail table, then there would be no way to restore both the data and the cache to their original states. Even though the call to Database1.Rollback would restore the database, there would be no way to restore the cache.
2、用TADOQuery,但不连接主从表关系。
从表的SQL内容是:SELECT * FROM 从表 WHERE 连接字段名=:查询参数名(当然,你也可以不加条件,而用Filter来进行)
在主表的afterScroll事件中写代码,当主表记录指针移动时,设从表查询参数值为主表的与从表的连接字段值,并Requery。而当从表新增记录时,手工给从表对应的连接字段赋值。