Support for optimistic locking version numbers.

Posts   
 
    
JamesUK
User
Posts: 7
Joined: 25-Oct-2005
# Posted on: 30-Oct-2005 02:11:40   

I think LLBLGen needs to support the concept of an entity version number mapped to standard integer sequence number columns in the DB schema. LLBLGen should take control of this column in all updates and abort an update if another thread of activity had already incremented the number.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 30-Oct-2005 10:00:38   

First of all, LLBLGen Pro doesnt lock rows because locking rows by an application outside the db can lead to performance degration, it leaves the locking to the RDBMS.

If you want concurrency based on a version field, you can do that yourself, using an IConcurrencyPredicateFactory implementation. At savetime LLBLGen pro will ask that factory for a special filter you produce which is used to make the save action only succeed if hte filter passes. I.o.w.: if the version number has changed, the save of course doesn't succeed.

See for documentation on this: Using the entity classes -> Concurrency Control.

Frans Bouma | Lead developer LLBLGen Pro
JamesUK
User
Posts: 7
Joined: 25-Oct-2005
# Posted on: 30-Oct-2005 12:02:05   

Otis wrote:

First of all, LLBLGen Pro doesn’t lock rows because locking rows by an application outside the db can lead to performance degradation, it leaves the locking to the RDBMS.

I am a bit confused, I am not asking for LLBLGen to implement an extra layer of object locking within the middle tier, this would not be effective in a load-balanced multi web server scenario anyhow.

I agree that locking should be avoided where possible which is why I wish to use optimistic locking. Optimistic locking based on update count version column is such a widespread design pattern a leading OR/M tool such as LLBLGen should implemented it out of the box. I would like to be able to mark a column in the designer as the versioned int column and then leave maintenance of this column to LLBLGen. LLBLGen should also generate the conditional TSQL to check the version number just prior to an update.

Otis wrote:

If you want concurrency based on a version field, you can do that yourself, using an IConcurrencyPredicateFactory implementation. At save time LLBLGen pro will ask that factory for a special filter you produce which is used to make the save action only succeed if hte filter passes.

Would my IConcurrencyPredicateFactory implementation have to query the DB independently of the save SQL or could I inject some extra TSQL into the update command?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 30-Oct-2005 13:07:46   

JamesUK wrote:

Otis wrote:

First of all, LLBLGen Pro doesn’t lock rows because locking rows by an application outside the db can lead to performance degradation, it leaves the locking to the RDBMS.

I am a bit confused, I am not asking for LLBLGen to implement an extra layer of object locking within the middle tier, this would not be effective in a load-balanced multi web server scenario anyhow.

I agree that locking should be avoided where possible which is why I wish to use optimistic locking. Optimistic locking based on update count version column is such a widespread design pattern a leading OR/M tool such as LLBLGen should implemented it out of the box. I would like to be able to mark a column in the designer as the versioned int column and then leave maintenance of this column to LLBLGen. LLBLGen should also generate the conditional TSQL to check the version number just prior to an update.

LLBLGen Pro doesn't do that, because it doesn't propagate any concurrency pattern, simply because actually, they're all not really effective. See for a discussion: http://weblogs.asp.net/fbouma/archive/2003/05/24/7499.aspx

They do work, but they also cause loss of work. It's best to avoid loss of work, instead of at the end, after the work has been done, consider all the work that has been done is useless.

Instead, it leaves it to the developer which scheme the developer wants to use and offers facilities to apply that scheme transparently inside the code. This avoids having a certain 'pattern' implemented which is not used by a large group of users because they want to implement concurrency differently.

Otis wrote:

If you want concurrency based on a version field, you can do that yourself, using an IConcurrencyPredicateFactory implementation. At save time LLBLGen pro will ask that factory for a special filter you produce which is used to make the save action only succeed if hte filter passes.

Would my IConcurrencyPredicateFactory implementation have to query the DB independently of the save SQL or could I inject some extra TSQL into the update command?

All you have to do is produce a PredicateExpression like:


PredicateExpression toReturn = new PredicateExpression();
OrderEntity order = (OrderEntity)containingEntity;

toReturn.Add(PredicateFactory.CompareValue(OrderFieldIndex.EmployeeID, 
  ComparisonOperator.Equal, order.Fields[(int)OrderFieldIndex.EmployeeID].DbValue));

(I used the verbose style of predicate construction here, just to be sure you know what's going on if you're using VB.NET 2003, which doesn't support operator overloading so you can't use the following code, because I also could have written:


toReturn = new PredicateExpression(OrderFields.EmployeeID == order.Fields[(int)OrderFieldIndex.EmployeeID].DbValue);

)

This is then appended to the update query for you. In my example above, I produce a filter which produces the SQL: Northwind.dbo.Orders.EmployeeID = @value

where @value is the value of DbValue of the EmployeeID field in the Order entity right before it's saved. DbValue is the property of an entity field which holds the value of the field when it was LOADED from the db. So say you load an order entity, you then manipulate it and you want to update it, but only if EmployeeID is still the same value as when you loaded that order. The above code assures that, because it passes to the filter the value of the EmployeeID field when the order was loaded. If someone changed the field in the db, the filter makes the update query to fail.

Frans Bouma | Lead developer LLBLGen Pro