[SOLVED] Concurrency (Timestamp, Adapter)

Posts   
 
    
BSAPD avatar
BSAPD
User
Posts: 42
Joined: 02-Jul-2004
# Posted on: 29-Oct-2004 00:46:03   

I am getting the following error when I try to update a record when the records timestamp has changed:

An exception was caught during the execution of an action query: Object must implement IConvertible.. Check InnerException, QueryExecuted and Parameters of this exception to examine the cause of this exception.

Here is my implementation of IConcurrencyPredicateFactory:


public class ConcurrencyPredicateFactory : IConcurrencyPredicateFactory
{
    public ConcurrencyPredicateFactory() {}
    
    public IPredicateExpression CreatePredicate(ConcurrencyPredicateType typeToCreate, object containingEntity)
    {
        IPredicateExpression concurrancyPredicate = new PredicateExpression();
        IEntity2 entity = (IEntity2)containingEntity;
        if(entity.Fields["RowVersion"] != null && typeToCreate == ConcurrencyPredicateType.Save)
        {
            EntityField2 rowVersionField = 
                new EntityField2("RowVersion", entity.LLBLGenProEntityName, typeof(System.Byte[]),
                    TypeDefaultValue.GetDefaultValue(typeof(System.Byte[])), false,
                     (int)entity.Fields["RowVersion"].FieldIndex, 8, 0, 0, false);
            FieldCompareValuePredicate compairRowVersion = 
                new FieldCompareValuePredicate((IEntityFieldCore)rowVersionField, null, ComparisonOperator.Equal,
                entity.Fields["RowVersion"]);
            concurrancyPredicate.Add(compairRowVersion);
        }
        return concurrancyPredicate;
    }
}

I am expecting to get an error but the error I am expecting is the RMConcurrencyException not the ORMQueryExecutionException.

Can anyone see whats wrong here???

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 29-Oct-2004 09:45:02   

Why don't you simple do:


//...
public IPredicateExpression CreatePredicate(ConcurrencyPredicateType typeToCreate, object containingEntity)
{
    IPredicateExpression concurrancyPredicate = new PredicateExpression();
    IEntity2 entity = (IEntity2)containingEntity;
    if(entity.Fields["RowVersion"] != null && typeToCreate == ConcurrencyPredicateType.Save)
    {
        concurrancyPredicate.Add(
                new FieldCompareValuePredicate(entity.Fields["RowVersion"], null, ComparisonOperator.Equal));
    }
    return concurrancyPredicate;
}

After all, it's just about generating SQL.

The convertable error is mostly caused by bad casting. I think it doesn't work because you specify the FIELD as a value, (... ComparisonOperator.Equal, entity.Fields["RowVersion"]) while you should do: ... ComparisonOperator.Equal, entity.Fields["RowVersion"].CurrentValue

Frans Bouma | Lead developer LLBLGen Pro
BSAPD avatar
BSAPD
User
Posts: 42
Joined: 02-Jul-2004
# Posted on: 29-Oct-2004 18:47:50   

Your sample works beautifully, Thanks! smile

I have one question though... What overload is this line using?

Otis wrote:

FieldCompareValuePredicate(entity.Fields["RowVersion"], null, ComparisonOperator.Equal));

The only overload that I can find that takes three parameter is:

public FieldCompareValuePredicate ( SD.LLBLGen.Pro.ORMSupportClasses.IEntityField field , SD.LLBLGen.Pro.ORMSupportClasses.ComparisonOperator comparisonOperator , System.Object value )

and that doesn't seem to match with your sample. I can see that your version is much simpler but I do not see that overload in the object browser. Again, your code works but I don't understand why...

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 29-Oct-2004 19:15:32   

BSAPD wrote:

Your sample works beautifully, Thanks! smile

I have one question though... What overload is this line using?

Otis wrote:

FieldCompareValuePredicate(entity.Fields["RowVersion"], null, ComparisonOperator.Equal));

The only overload that I can find that takes three parameter is:

public FieldCompareValuePredicate ( SD.LLBLGen.Pro.ORMSupportClasses.IEntityField field , SD.LLBLGen.Pro.ORMSupportClasses.ComparisonOperator comparisonOperator , System.Object value )

and that doesn't seem to match with your sample. I can see that your version is much simpler but I do not see that overload in the object browser. Again, your code works but I don't understand why...

This one: public FieldCompareValuePredicate ( SD.LLBLGen.Pro.ORMSupportClasses.IEntityFieldCore field , SD.LLBLGen.Pro.ORMSupportClasses.IFieldPersistenceInfo persistenceInfo , SD.LLBLGen.Pro.ORMSupportClasses.ComparisonOperator comparisonOperator ) simple_smile

It will take the value of the field passed in as compare value. You can also compare against the DbValue (the original value read from the db) if you like, (with this timestamp field, that's not useful, but in other cases it might) simple_smile

Frans Bouma | Lead developer LLBLGen Pro
Bposter
User
Posts: 4
Joined: 27-Sep-2004
# Posted on: 10-Nov-2004 18:14:32   

I'm trying to following (copy) this example. How do I actually use it? When I am ready to do an update, what would the code look like?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 10-Nov-2004 19:00:31   

Bposter wrote:

I'm trying to following (copy) this example. How do I actually use it? When I am ready to do an update, what would the code look like?

The concurrencypredicatefactory produces a predicate when called by the save logic and that predicate is added to the save action, so the predicate will end up in the WHERE clause and can therefore make sure the update is only executed when the predicate is true.

You add an instance of the concurrencypredicatefactory implementation to the entity instance (set the ConcurrencyPredicateFactoryToUse) and when the entity is saved, the factory is called.

Frans Bouma | Lead developer LLBLGen Pro