Field Compare Expression

Posts   
 
    
mpe
User
Posts: 8
Joined: 07-Oct-2005
# Posted on: 07-Oct-2005 01:18:51   

Hi, I'm trying to do a bitwise compare expression (adapter, sql server) similar to :

select lastname, firstname, attributes from Candidate where Attributes = (Attributes | 1)

the code I've arrived at is:

expression.Add(new FieldCompareExpressionPredicate( candidate.Fields["Attributes"], null, ComparisonOperator.Equal, new Expression(candidate.Fields["Attributes"], ExOp.BitwiseOr, attributes)));

When this hits the dataccess adapter I get the following exception:

Object reference not set to an instance of an object. at SD.LLBLGen.Pro.ORMSupportClasses.Expression.ToQueryText(Int32& uniqueMarker, Boolean inHavingClause) at SD.LLBLGen.Pro.ORMSupportClasses.FieldCompareExpressionPredicate.ToQueryText(Int32& uniqueMarker, Boolean inHavingClause)

I've verified all the values I'm setting are indeed set, and am at a loss as to why this doesn't work. Any ideas what I'm missing?

Thanks, Mike

bclubb
User
Posts: 934
Joined: 12-Feb-2004
# Posted on: 07-Oct-2005 03:01:57   

Can you step into each arguement and see if the error is caused when accessing any of the parameters which are in the Add method?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 07-Oct-2005 09:47:52   

You re-use the field object of an entity. If you create NEW field objects, does that make a difference?

Frans Bouma | Lead developer LLBLGen Pro
mpe
User
Posts: 8
Joined: 07-Oct-2005
# Posted on: 07-Oct-2005 15:48:41   

The candidate entity is created just before building the expression - I've also tried EntityFieldFactory.Create() and CandidateEntityFactory().CreateFields(). The project includes a broad array of other predicate types using EntityFieldFactory.Create(), which I've not had any problems with.

I can step through the code and see all the fields/arguements as expected - the 'Field' property displays an error - but I'm guessing thats because it's adapter code, 'FieldCore' is ok.

Also tried simplifying the expression to be something like 'field = field' and still get the same error.

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 07-Oct-2005 16:14:11   

What's the "Attribute" datatype?

I think it should have a numeric datatype

mpe
User
Posts: 8
Joined: 07-Oct-2005
# Posted on: 07-Oct-2005 16:31:48   

attribute is an int

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 07-Oct-2005 16:48:05   

The ToQueryText is a routine without any object method calls, except for the db specific creator. Which is always set through the DQE.

If you rewrite the statement like:


expression.Add(new FieldCompareExpressionPredicate(
    EntityFieldFactory.Create(CandidateFieldIndex.Attributes), null, 
    ComparisonOperator.Equal,
    new Expression(EntityFieldFactory.Create(CandidateFieldIndex.Attributes), ExOp.BitwiseOr, attributes)));

does it work then? If not, I'm out of options, and you should try with a debug build of the runtime libraries, which can be created from the sourcecode in the llblgen pro installation folder to see which line causes teh problem.

Frans Bouma | Lead developer LLBLGen Pro
mpe
User
Posts: 8
Joined: 07-Oct-2005
# Posted on: 07-Oct-2005 21:18:16   

I couldn't run the debug code from my project - it threw all kinds of exceptions about enums being required and non root prefetches. I'm guessing there's version issues (.net 1.0/1.1) references/strong names (we've gac'd the release SupportClasses dll) etc, and something may have been hanging on to a release ref somewhere (it's a large stack)

I was able to build a new project from the ground up using the ORMSupportClasses code and simuate the code - where it worked w/o problem. I ran both the project and test code side by side - breaking on: m_adapter.FetchEntityCollection(coll, filters, 0, sorting, prefetches);

Examing the filters variable shows the the project is initialized exactly as the test code - yet the project code will throw the exception as soon as it attempts to execute that line.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 07-Oct-2005 21:48:54   

So you have a new project which works without a problem, but your old project throws an exception? Do you by any chance reference the .NET10.dll version instead of the .NET11.dll version? (it's an easy to make mistake, but can have weird errors)

Frans Bouma | Lead developer LLBLGen Pro
mpe
User
Posts: 8
Joined: 07-Oct-2005
# Posted on: 08-Oct-2005 04:24:58   

OK - I was able to reproduce in the new project. This looks like a serialization issue. One thing I didn't mention is we build the predicates on the client and send them over the wire as a byte array. Using entities of your choice line 330 of Expression.cs throws when the serialize code executes:

    private void buttonCrashTest_Click(object sender, System.EventArgs e)
    {
        RelationPredicateBucket bucket = new RelationPredicateBucket();
        IPredicateExpression expression  = new PredicateExpression();
        int attributes = 16;    

        expression.Add(new FieldCompareExpressionPredicate(
            EntityFieldFactory.Create(CandidateFieldIndex.Attributes), null,
            ComparisonOperator.Equal,
            new Expression(EntityFieldFactory.Create(CandidateFieldIndex.Attributes), ExOp.BitwiseOr, attributes)));

        bucket.PredicateExpression.Add(expression);

        if(this.checkBox_Serialize.Checked)
        {
            byte[] o = ObjectToByteArray(bucket);
            bucket = ByteArrayToObject(o) as RelationPredicateBucket;
        }


        DataAccessAdapter m_adapter = new DataAccessAdapter();
        EntityCollection coll = new EntityCollection(new CandidateEntityFactory());

        m_adapter.FetchEntityCollection(coll, bucket, 0, null, null);


        int x =  coll.Count;        
    }


    static public Byte [] ObjectToByteArray(object obj)
    {
        Byte [] buffer = null;
        IFormatter f = new BinaryFormatter();
        MemoryStream  stream = new MemoryStream();
        f.Serialize(stream, obj);
        buffer = stream.ToArray();
        return buffer;
    }

    static public object ByteArrayToObject(Byte[] data)
    {
        MemoryStream stream = new MemoryStream(data);
        IFormatter f = new BinaryFormatter();
        object obj=(object)f.Deserialize(stream);
        return obj;
    }
mpe
User
Posts: 8
Joined: 07-Oct-2005
# Posted on: 08-Oct-2005 05:07:33   

Looks like InitClass() never gets called when deserializing. Making the changes below in expression.cs gets me going again:

    public ArrayList Parameters 
    {
        get 
        { 
            **if (_parameters == null) 
                _parameters = new ArrayList(); **
            return _parameters;
        }
    }

and

    public string ToQueryText(ref int uniqueMarker, bool inHavingClause)
    {

...

        ~~_parameters.Clear();~~
        **Parameters.Clear(); **

I guess the question now is: What are the chances of getting a supported fix, assuming it's not already in a patch we haven't applied?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 08-Oct-2005 10:43:20   

I can't find a buglog about this, though I do remember something related to this. As expression has an empty constructor which calls InitClass() it should call it while deserializing. I'll check it out, it's easy to check now I know where to look simple_smile Thanks for testing/check what the problem is.

If the bug is still there, you obviously get a fixed runtime today.

(edit) I remembered the issue, I had exactly the same problem with Predicate, which has the same fix you proposed smile . I'll fix the code later today.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 08-Oct-2005 13:47:04   

Fix is now available: Download the latest runtime libraries from the customer area -> runtime libraries section. If you're using old templates (before May 25th), also upgrade the templates.

Frans Bouma | Lead developer LLBLGen Pro
mpe
User
Posts: 8
Joined: 07-Oct-2005
# Posted on: 10-Oct-2005 15:47:58   

Thanks for the quick response - however after installing the latest build the problem remains - I checked the source code and didn't see anything different in the way _parameters is initialized.

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 10-Oct-2005 16:20:00   

Would you please make sure that your code refers to the new installed binaries

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 10-Oct-2005 16:20:42   

mpe wrote:

Thanks for the quick response - however after installing the latest build the problem remains - I checked the source code and didn't see anything different in the way _parameters is initialized.

Are you sure you're using the newest runtimes, as my unittests to test the problem now succeed, and failed before.

I implemented ISerializable on the class now, and _parameters is now defined in the ISerializable constructor.

Frans Bouma | Lead developer LLBLGen Pro
mpe
User
Posts: 8
Joined: 07-Oct-2005
# Posted on: 10-Oct-2005 16:38:31   

It works fine in my test project - something must still be hanging on to an old ref somewhere. Sorry for the bother and thanks again for the fast turnaround!