Bug in Refreshing records after RollBack (7.0.0.2)
-
alex.santanna
- Posts: 4
- Joined: Fri 23 Jan 2009 20:05
Bug in Refreshing records after RollBack (7.0.0.2)
A form with one TOraSession in direct mode (oracle 10g R2), one TOraQuery cacheupdate enabled with a TOraDataSource linked to it.
A TCRDBGrid linked with TOraDataSource.
Table with only one record and one field ID value 1.
Steps to reproduce:
StartTransaction;
Edit the record, change the value from 1 to 2.
Post;
Applyupdates;
Commit;
The database is updated.
The Grid display the correct value.
Now the bug, without closing the program:
StartTransaction;
Insert one record;
Cancel;
CancelUpdates;
Rollback;
The previous record edited show the value 1 insted of 2, but the value in the database is 2.
The rollback command rollsback a commited transaction.
A TCRDBGrid linked with TOraDataSource.
Table with only one record and one field ID value 1.
Steps to reproduce:
StartTransaction;
Edit the record, change the value from 1 to 2.
Post;
Applyupdates;
Commit;
The database is updated.
The Grid display the correct value.
Now the bug, without closing the program:
StartTransaction;
Insert one record;
Cancel;
CancelUpdates;
Rollback;
The previous record edited show the value 1 insted of 2, but the value in the database is 2.
The rollback command rollsback a commited transaction.
Hello,
To resolve the problem you should call the CommitUpdates method to clear the cached updates buffer after successful call to ApplyUpdates and database component's Commit methods.
For example:
with MyQuery do
begin
Session.StartTransaction;
try
... {Modify data}
ApplyUpdates; {try to write the updates to the database}
Session.Commit; {on success, commit the changes}
except
RestoreUpdates; {restore update result for applied records}
Session.Rollback; {on failure, undo the changes}
raise; {raise the exception to prevent a call to CommitUpdates!}
end;
CommitUpdates; {on success, clear the cache}
end;
end;
or you can call only the CommitUpdates method, and it will call the ApplyUpdates method automatically.
For more information please see the TMemDataSet.ApplyUpdates Method and the TMemDataSet.CommitUpdates Method topics in the ODAC help.
To resolve the problem you should call the CommitUpdates method to clear the cached updates buffer after successful call to ApplyUpdates and database component's Commit methods.
For example:
with MyQuery do
begin
Session.StartTransaction;
try
... {Modify data}
ApplyUpdates; {try to write the updates to the database}
Session.Commit; {on success, commit the changes}
except
RestoreUpdates; {restore update result for applied records}
Session.Rollback; {on failure, undo the changes}
raise; {raise the exception to prevent a call to CommitUpdates!}
end;
CommitUpdates; {on success, clear the cache}
end;
end;
or you can call only the CommitUpdates method, and it will call the ApplyUpdates method automatically.
For more information please see the TMemDataSet.ApplyUpdates Method and the TMemDataSet.CommitUpdates Method topics in the ODAC help.
-
alex.santanna
- Posts: 4
- Joined: Fri 23 Jan 2009 20:05
Hi Alex,
assume that I call ApplyUpdates for multiple queries in one transaction and one of the queries raises an error.
Do I have to call RestoreUpdates for
- All queries in transaction?
- All queries that have called ApplyUpdates before?
- Same as 2, but without query raising the exception?
- Only for query raising the exception?
Recently I have lost the latest input (query state was dsInsert) when calling RestoreUpdates ... do I have to call RestoreUpdates when query is in dsInsert or dsEdit? Or do I have to call Post/CheckBrowseMode before calling ApplyUpdates?
Thanks
assume that I call ApplyUpdates for multiple queries in one transaction and one of the queries raises an error.
Do I have to call RestoreUpdates for
- All queries in transaction?
- All queries that have called ApplyUpdates before?
- Same as 2, but without query raising the exception?
- Only for query raising the exception?
Recently I have lost the latest input (query state was dsInsert) when calling RestoreUpdates ... do I have to call RestoreUpdates when query is in dsInsert or dsEdit? Or do I have to call Post/CheckBrowseMode before calling ApplyUpdates?
Thanks
AlexP wrote:Hello,
To resolve the problem you should call the CommitUpdates method to clear the cached updates buffer after successful call to ApplyUpdates and database component's Commit methods.
For example:
with MyQuery do
begin
Session.StartTransaction;
try
... {Modify data}
ApplyUpdates; {try to write the updates to the database}
Session.Commit; {on success, commit the changes}
except
RestoreUpdates; {restore update result for applied records}
Session.Rollback; {on failure, undo the changes}
raise; {raise the exception to prevent a call to CommitUpdates!}
end;
CommitUpdates; {on success, clear the cache}
end;
end;
or you can call only the CommitUpdates method, and it will call the ApplyUpdates method automatically.
For more information please see the TMemDataSet.ApplyUpdates Method and the TMemDataSet.CommitUpdates Method topics in the ODAC help.
Hello
The answer depends on your application behavior. What do you do when one query raises an error? Do you rollback transaction?
If you rollback transaction on a raised error, then you should call RestoreUpdates for all queries that have called ApplyUpdates before.
If you don't rollback transaction on a raised error, then you you shouldn't call RestoreUpdates at all. In this case you should modify the record that wasn't stored to database (raised the error) and repeat ApplyUpdate for this dataset. A record form this dataset that was stored successfully, wasn't stored iteratively. If you call RestoreUpdates then some records can be stored iteratively and you can get error, for example, unique key validation if the same record is inserted iteratively.
But updating database in transaction is a more preferable method because it allows avoiding partially database updating.
The answer depends on your application behavior. What do you do when one query raises an error? Do you rollback transaction?
If you rollback transaction on a raised error, then you should call RestoreUpdates for all queries that have called ApplyUpdates before.
If you don't rollback transaction on a raised error, then you you shouldn't call RestoreUpdates at all. In this case you should modify the record that wasn't stored to database (raised the error) and repeat ApplyUpdate for this dataset. A record form this dataset that was stored successfully, wasn't stored iteratively. If you call RestoreUpdates then some records can be stored iteratively and you can get error, for example, unique key validation if the same record is inserted iteratively.
But updating database in transaction is a more preferable method because it allows avoiding partially database updating.
Hi bork,
- Is it possible to check in code if ApplyUpdates was called before, or do I have to remember the query objects on my own?
- Does it harm to call RestoreUpdates on queries, that did not call ApplyUpdates before?
- Should I call RestoreUpdates on the query raising the exception?
- Should I call CheckBrowseMode/Post before calling ApplyUpdates, when DataSet is in dsInsert/dsEdit?
Yes, I will rollback the transaction.bork wrote:Hello
The answer depends on your application behavior. What do you do when one query raises an error? Do you rollback transaction?
If you rollback transaction on a raised error, then you should call RestoreUpdates for all queries that have called ApplyUpdates before.
- Is it possible to check in code if ApplyUpdates was called before, or do I have to remember the query objects on my own?
- Does it harm to call RestoreUpdates on queries, that did not call ApplyUpdates before?
- Should I call RestoreUpdates on the query raising the exception?
- Should I call CheckBrowseMode/Post before calling ApplyUpdates, when DataSet is in dsInsert/dsEdit?
Hello,
- You can use the UpdateResult method to read the status of the latest call to the ApplyUpdates method while cached updates are enabled.
- You can call the RestoreUpdate method without calling the ApplyUpdates method without any harm.
- You should call RestoreUpdates on a query raising an exception.
- You shouldn't call CheckBrowseMode/Post before calling ApplyUpdates whenDataSet is in dsInsert/dsEdit. But DataSet should be open before calling the ApplyUpdates method.
- You can use the UpdateResult method to read the status of the latest call to the ApplyUpdates method while cached updates are enabled.
- You can call the RestoreUpdate method without calling the ApplyUpdates method without any harm.
- You should call RestoreUpdates on a query raising an exception.
- You shouldn't call CheckBrowseMode/Post before calling ApplyUpdates whenDataSet is in dsInsert/dsEdit. But DataSet should be open before calling the ApplyUpdates method.