modify fields before ConcurrencyPredicate is built

Posts   
 
    
JuergenF
User
Posts: 29
Joined: 23-May-2006
# Posted on: 29-Oct-2013 21:05:27   

Hi

We are using a ConcurrencyPredicateFactory. Before saving we want to change the values of some fields, eg 'EditMode' in a central location like CommonEntityBase, depending on some other properties.

Problem is, the ConcurrencyPredicate is built rather early but we need the changed values in the predicate. So far we haven't found an event/overridable method like 'OnBeforeSave' which is called before the predicate is built.

So, is there such a method? Any other way to do this?

TIA, Juergen

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 30-Oct-2013 07:04:45   

At ConcurrencyPredicateFactory you have both the currentValue and dbValue. What is the point of changing the current value of a field before that? Why not just changing it before you call .Save?

Could you illustrate more your case?

David Elizondo | LLBLGen Support Team
JuergenF
User
Posts: 29
Joined: 23-May-2006
# Posted on: 30-Oct-2013 09:29:12   

Hi, thanks for answering.

We are implementing pessimistic locking. We have a 'Lock' method that sets the 'EditMode'-Flag to true and then saves the entity. Any other save should reset 'EditMode' to false. The problem is that the predicate should prevent double locks and so looks at DBValue and Currentvalue of this 'EditMode' field, they mustn't both be true...

We could of course reset the flag manually anytime we call .Save or .AddForSave - just trying to be lazy wink

Walaa avatar
Walaa
Support Team
Posts: 14946
Joined: 21-Aug-2005
# Posted on: 30-Oct-2013 19:38:21   

I don't believe that's the best use of the ConcurrencyPredicateFactory. Your case seems to me unrelated to concurrency.

A concurrency field should not be altered in your code, otherwise it's just a field and a filtering logic, but not a concurrency one, which is built early in the process. Also a Boolean won't be a good option for a concurrency field.

JuergenF
User
Posts: 29
Joined: 23-May-2006
# Posted on: 30-Oct-2013 20:48:22   

The 'EditMode' isn't the only field we look at, we also have an UserId...

Optimistic locking with a ConcurrencyPredicateFactory seems simple to implement. But reading http://www.llblgen.com/TinyForum/Messages.aspx?ThreadID=10960 I thought with a ConcurrencyPredicateFactory it should also be possible to implement pessimistic locking with 'logical' locks on rows ('to implement your own concurrency support the way it fits your needs' wink ).

Since there seem no examples other than with optimistic locking, we are struggling a bit to get it work.

But if we find a nice way to 'unlock' an entity on saving, even if it has to be done manually before calling .Save, I think we should be fine with the predicate we have so far.

Thanks for answering Juergen

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 31-Oct-2013 16:21:28   

I think some things are mixed up here: the concurrencypredicate factory is meant to produce predicates (so, filters) on save to make an update fail if the predicate resolves to false. I.o.w.: the factory itself doesn't do anything other than producing a predicate which defines when the update fails or succeeds. It can't change state, the update statement does.

So the way to implement it is: the update which has a predicate which resolves to true, will succeed, the others will fail.

One could do this by adding a field which is your lock value. You set that field to a value, X (e.g a GUID), if it's NULL, which means the code which set the field is also owning the lock. Then execute an update which has an extra predicate which tests whether the extra field has the value X. No other code has that lock value, and all updates will fail.

Pessimistic locks are meant to make code wait. So the code which wants to set the value of the extra field to its own lock value and which is faced with failing updates because the value is already set (so the row is 'locked') has to wait till it succeeds.

In the end, it IMHO doesn't really matter what you use: in general whatever you choose makes one keep its work and the other one lose its work, unless you merge the two, or you avoid the one who would lose his/her work not start the work in the first place.

Frans Bouma | Lead developer LLBLGen Pro
JuergenF
User
Posts: 29
Joined: 23-May-2006
# Posted on: 01-Nov-2013 13:44:36   

Otis wrote:

or you avoid the one who would lose his/her work not start the work in the first place.

Yepp, this is how we want it to work: - First user locks and starts to work. - Second user locks - at least tries to, but gets a ConcurrencyException and no changes are allowed.

I think with a little hack we got it to work now, so I'm closing this thread.

Thanks @all for answering.