How to guarantee data integrity on update

Posts   
 
    
KAF
User
Posts: 18
Joined: 13-Oct-2005
# Posted on: 19-Oct-2005 12:28:12   

Hi,

Oracle got a "select ... for update" statement that locks the involved rows so that no other process can update them util the lock is released. I guess there is no support for this in LLBLGen?

My multi user scenario is like this: I read a row (on the server), send it to the client that updates the data, the row is returned (to the server) to be updated and I can then check to see if any other users have made changes to the row (and handle it respectively). But is there any mechanism that guaranties that from the moment I read/compare my data from the client against the data in the database and the update is carried out, that no other process has updated the very same row? How do I guarantee that the data hasn't been changed inbetween my read and my update? As i understand there is no point in using transaction management on a read command.

What am I missing here?

I can think of 3 scenarios that would do the trick (in Oracle): - "select ... for update" - "update table xxx set rowid = rowid" (creates a lock) - LLBGen handles this in some way

I use an Oracle database with an adapter scenario.

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 19-Oct-2005 16:13:41   

LLBLGen doesn't lock rows, as that can hurt performance. You should use a ConcurrencyPredicateFactory and compare old values with new values or use a timestamp-esk column (oracle doesn't have a timestamp column).

Please refer to the "Concurrency Control" section in the LLBLGen Pro documentation, under "Using the generated code" -> "Adapter/Selfservicing" -> "Using the Entity Classes"

KAF
User
Posts: 18
Joined: 13-Oct-2005
# Posted on: 20-Oct-2005 13:09:32   

Thanks for the fast reply!

I have read the documentation and I am aware of that it is possible to implement a mechanism that compares values to evaluate if the row has changed since last fetch.

But the values I compare against must be fetched from the database at some point, so how can I be certain that the row hasn't been updated after I fetched it? I assume I can't built the the selct and update into an atomic operation unless I first lock the row before fetching it (hence "select for update" or other locking mechanisms)?

As I understand there is no support for such a scenario i LLBLGen, so I should implement it myself to make sure data is not owerwritten.

pilotboba
User
Posts: 434
Joined: 05-Aug-2005
# Posted on: 20-Oct-2005 18:40:54   

KAF wrote:

But the values I compare against must be fetched from the database at some point, so how can I be certain that the row hasn't been updated after I fetched it?

No, they are not fetched, the compare is done in the UPDATE transaction.

Let's say you do a fetch of:

SELECT * FROM Customers

So, when you update your statement looks like this:

UPDATE Customers SET FirstName = "New name" WHERE [id] = 1 and [FirstName] = "Old Name"

If FirstName, the value you changed is still the same value it was when you retrieved the record "Old Name" then the update will be succesful. But, if FirstName now has a value of "Newer Name" then your Update will fail.

BTW: You have to code this predicate yourself, LLBLGen Pro doesn't do it out of the box. (I think). Although it would be nice if it had an option to.

BOb

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 20-Oct-2005 18:53:57   

pilotboba wrote:

BTW: You have to code this predicate yourself, LLBLGen Pro doesn't do it out of the box. (I think). Although it would be nice if it had an option to.

To be as flexible as possible, the developer should program a ConcurrencyPredicateFactory, which produces the filters for the entity. This can be a simple loop which produces fieldcomparevalue predicates for all fields which are in the entity. It can also be a routine which checks for timestamp columns or other change tracking columns.

Thanks for your answer btw simple_smile

Frans Bouma | Lead developer LLBLGen Pro