Bug in Refreshing records after RollBack (7.0.0.2)

Discussion of open issues, suggestions and bugs regarding ODAC (Oracle Data Access Components) for Delphi, C++Builder, Lazarus (and FPC)
Post Reply
alex.santanna
Posts: 4
Joined: Fri 23 Jan 2009 20:05

Bug in Refreshing records after RollBack (7.0.0.2)

Post by alex.santanna » Thu 02 Dec 2010 15:47

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.

AlexP
Devart Team
Posts: 5530
Joined: Tue 10 Aug 2010 11:35

Post by AlexP » Fri 03 Dec 2010 08:34

Hello,

Thank you for the information.
We have reproduced the problem.
We will notify you as soon as we have any results.

AlexP
Devart Team
Posts: 5530
Joined: Tue 10 Aug 2010 11:35

Post by AlexP » Fri 03 Dec 2010 11:57

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.

alex.santanna
Posts: 4
Joined: Fri 23 Jan 2009 20:05

Post by alex.santanna » Mon 06 Dec 2010 13:53

Alex,

Thank you for your response, I'll do that.

best regards,

a-s-z
Posts: 106
Joined: Wed 03 Dec 2008 06:01

Post by a-s-z » Wed 15 Dec 2010 08:09

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
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.

bork
Devart Team
Posts: 649
Joined: Fri 12 Mar 2010 07:55

Post by bork » Wed 15 Dec 2010 14:54

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.

a-s-z
Posts: 106
Joined: Wed 03 Dec 2008 06:01

Post by a-s-z » Thu 16 Dec 2010 07:50

Hi bork,
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.
Yes, I will rollback the transaction.

- 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?

AlexP
Devart Team
Posts: 5530
Joined: Tue 10 Aug 2010 11:35

Post by AlexP » Thu 16 Dec 2010 13:26

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.

Post Reply