2.5: FindMatches on supertype causes ORMInterpretationException.

Posts   
 
    
PatrickD
User
Posts: 65
Joined: 05-Sep-2006
# Posted on: 24-Aug-2007 16:59:37   

Hi,

First congrats with the release of 2.5! Everything seems to still work great, hopefully I get some time to learn the new features.

I have however encountered my first bug. This worked in version 2.0 but not in 2.5:

I have a supertype Identification with a subtype LicensePlate.

When I call the following code on the subtype, everything goes well:


        [Test(Description = "TEST with subtype")]
        public void TEST()
        {
            LicensePlateCollection licensePlateCollection = new LicensePlateCollection();
            licensePlateCollection.GetMulti(null);
            List<int> matches = licensePlateCollection.FindMatches(LicensePlateFields.LicensePlate == "AB-01-CD");
            Assert.AreEqual(1, matches.Count);
        }

However when I do the same call on the supertype:


        [Test(Description = "TEST with supertype")]
        public void TEST2()
        {
            IdentificationCollection identificationCollection = new IdentificationCollection();
            identificationCollection.GetMulti(null);
            List<int> matches = identificationCollection.FindMatches(LicensePlateFields.LicensePlate == "AB-01-CD");
            Assert.AreEqual(1, matches.Count);
        }

I get the following exception:


SD.LLBLGen.Pro.ORMSupportClasses.ORMInterpretationException: Field value and value to compare with aren't of the same type. Field value is of type 'System.Int32', value to compare with is of type 'System.String'

at SD.LLBLGen.Pro.ORMSupportClasses.FieldCompareValuePredicate.InterpretPredicate(IEntityCore entity) 
at SD.LLBLGen.Pro.ORMSupportClasses.Predicate.SD.LLBLGen.Pro.ORMSupportClasses.IPredicateInterpret.Interpret(IEntityCore entity) 
at SD.LLBLGen.Pro.ORMSupportClasses.CollectionCore`1.FindMatches(IPredicate filter) 
at TestFixture.TEST2() 

LicensePlate is a field of type varchar(30) and is defined only in the subtype. As I stated before, this worked in version 2.0.

Regards,

Patrick

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 26-Aug-2007 12:44:05   

Please either mail the .lgp file to support AT llblgen.com or attach it here, or create a helpdesk thread and attach it there. the code which throws the exception is very simple and leaves no room for error so something else is going on:


protected override bool InterpretPredicate( IEntityCore entity )
{
    if(_field == null) 
    {
        return false;
    }

    object fieldValue = ((IEntityFieldCoreInterpret)_field).GetValue( entity );
    object valueToCompareWith = _value;

    if((fieldValue == null)||(fieldValue==DBNull.Value))
    {
        return false;
    }
    
    Type typeFieldValue = fieldValue.GetType();
    Type typeValueToCompareWith = valueToCompareWith.GetType();
    if(typeFieldValue != typeValueToCompareWith)
    {
        try
        {
            valueToCompareWith = Convert.ChangeType(valueToCompareWith, typeFieldValue, null);
        }
        catch
        {
            // conversion failed.
            throw new ORMInterpretationException(
                    string.Format("Field value and value to compare with aren't of the same type. Field value is of type '{0}', value to compare with is of type '{1}'",
                        typeFieldValue, typeValueToCompareWith));
        }
    }
//...

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 27-Aug-2007 14:15:14   

Reproduced in a collection with multiple types (Employees with subtype instances of clerk, manager, boardmember)

[Test]
public void FieldCompareValueTestOnSubtypeFieldsWithSuperTypeCollection()
{
    List<IEntity> toDelete = new List<IEntity>();
    UnitOfWork uow = CreateTestBatchForSave2(ref toDelete);
    uow.Commit(new Transaction(IsolationLevel.ReadCommitted, "Save"), true);

    EmployeeCollection employees = new EmployeeCollection();
    employees.GetMulti(null);
    List<int> matches = employees.FindMatches(ClerkFields.JobDescription == "pushing paper");
    Assert.AreEqual(1, matches.Count);

    DeleteSavedEntities(toDelete);
}

(edit) it's caused by the fact that the field's value is obtained wrong for entities which don't have the field (e.g. supertypes, or sibling types): it uses the field index, which is of course not correct, it should use the name. It has the same issue on v2.0, but there it is less tolerant for types, so if the types don't match, it will simply return false, in v2.5 it will try to convert one to the other type (so you can compare byte values with ints for example) and if that fails it will throw an exception so you know your code isn't correct. Of course, then our code has to be correct first. simple_smile

Fixed in next build (released later today).

Frans Bouma | Lead developer LLBLGen Pro