Creating a PredicateExpression with And and Or

Posts   
 
    
Posts: 30
Joined: 08-Apr-2008
# Posted on: 29-Jun-2008 10:12:08   

Hi!

Since my last post to this forum, our project got a licensed copy of LLBLGen Pro 2.5 and we've been using it for most of the database operations of the system. There are a couple of complicated SQL queries for which we prefer to use database views, but it's mostly because our SQL-writing skills are higher than our LLBLGen-API-using skills flushed

We've recently traced a bug in our application that results from an improper combination of And-Or operators and what we're trying to do is this: Get rows from the table for a specific employer with either the inactive flag set or a date older than today's. In SQL, we would write it as: Workbooks.EmployerId = 6 AND (Workbooks.Inactive = 1 OR Workbooks.ExpiryDate < CURRENT_DATE)

What I'd like to know is how would we specify this condition when using LLBLGen?

Regards, Nitin

simmotech
User
Posts: 1024
Joined: 01-Feb-2006
# Posted on: 29-Jun-2008 10:18:25   

nitin.reddy wrote:

Hi!

Since my last post to this forum, our project got a licensed copy of LLBLGen Pro 2.5 and we've been using it for most of the database operations of the system. There are a couple of complicated SQL queries for which we prefer to use database views, but it's mostly because our SQL-writing skills are higher than our LLBLGen-API-using skills flushed

We've recently traced a bug in our application that results from an improper combination of And-Or operators and what we're trying to do is this: Get rows from the table for a specific employer with either the inactive flag set or a date older than today's. In SQL, we would write it as: Workbooks.EmployerId = 6 AND (Workbooks.Inactive = 1 OR Workbooks.ExpiryDate < CURRENT_DATE)

What I'd like to know is how would we specify this condition when using LLBLGen?

Regards, Nitin

Brackets are evaluated when creating filters (IPredicates) and you can use '&' and '|' for AND and OR respectively.

I'm guessing something like

WorkbooksFields.EmployerID == 6 & (WorkbooksFields.Inactive == 1 | WorkbooksFields.ExpiryDate < DateTime.Today)

Cheers Simon

Posts: 30
Joined: 08-Apr-2008
# Posted on: 29-Jun-2008 10:26:06   

Brackets are evaluated when creating filters (IPredicates) and you can use '&' and '|' for AND and OR respectively.

I'm guessing something like

WorkbooksFields.EmployerID == 6 & (WorkbooksFields.Inactive == 1 | WorkbooksFields.ExpiryDate < DateTime.Today)

Cheers Simon

Hi!

Thanks for the solution.

In my code, I'm adding conditions based on input criteria so it isn't practical to add all of it on the same line so I'm thinking I could perhaps there's some way to create the condition using the Add* methods.

BTW, when we do something like: RelationPredicateBucket rpb = new RelationPredicateBucket(EmployerFields.Id > 50); why doesn't .NET evaluate the "EmployerFields.Id > 50" and pass the result of the expression as boolean to the constructor of RelationPredicateBucket?

Whenever I've used predicates, I had to use some ugly syntax along the lines of: object retVal = methodToCall(input, delegate(int x) { if (x>10) return true; else return false; } );

-Nitin

EDIT: Is it possible to pass in a string for the RelationPredicateBucket to parse? That would make incremental construction of the predicate expression much easier.

stefcl
User
Posts: 210
Joined: 23-Jun-2007
# Posted on: 29-Jun-2008 11:04:43   

EDIT: Is it possible to pass in a string for the RelationPredicateBucket to parse? That would make incremental construction of the predicate expression much easier.

Why would you want to do that?????? That would totally defeat the concept of typed, compile-time checked queries without adding ANY value.

Let's have a look at this filter :

Workbooks.EmployerId = 6 AND (Workbooks.Inactive = 1 OR Workbooks.ExpiryDate < DateTime.Today)

You notice that there are two expressions in it :

1) Workbooks.EmployerId = 6 2) (Workbooks.Inactive = 1 OR Workbooks.ExpiryDate < DateTime.Today)

You first declare a RelationPredicateBucket :

RelationPredicateBucket filter = new RelationPredicateBucket();

Now let's declare the first expression :

PredicateExpression expr1 = new PredicateExpression();
expr1.Add( Workbooks.EmployerId = 6 );

Then the second :

PredicateExpression expr2 = new PredicateExpression();
expr2.Add( Workbooks.Inactive = 1 );
expr2.AddWithOr( Workbooks.ExpiryDate < DateTime.Today );

Now, let's combine these two expressions in our filter :

filter.PredicateExpression.Add( expr1 );
filter.PredicateExpression.Add( expr2 );

You're done... You can achieve the same result with fewer lines of code.

Posts: 30
Joined: 08-Apr-2008
# Posted on: 29-Jun-2008 11:10:52   

Hi!

Thanks for the solution. That's exactly what I've been looking for!

About the code:


expr2.AddWithOr( Workbooks.ExpiryDate < DateTime.Today );

I'm still wondering... why doesn't .NET evaluate the expression "Workbooks.ExpiryDate < DateTime.Today" and pass it as a parameter to the function confused - how does it know this is a predicate function without using the delegate keyword?

stefcl
User
Posts: 210
Joined: 23-Jun-2007
# Posted on: 29-Jun-2008 11:45:49   

Simply because the operators you use with your entity fields ( < > | & % == ) have been overloaded....

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39612
Joined: 17-Aug-2003
# Posted on: 29-Jun-2008 11:53:34   

stefcl wrote:

Simply because the operators you use with your entity fields ( < > | & % == ) have been overloaded....

Exactly simple_smile Look at it as a poor-mans linq in the pre-linq era wink

Frans Bouma | Lead developer LLBLGen Pro
Posts: 30
Joined: 08-Apr-2008
# Posted on: 29-Jun-2008 12:01:59   

Otis wrote:

stefcl wrote:

Simply because the operators you use with your entity fields ( < > | & % == ) have been overloaded....

Exactly simple_smile Look at it as a poor-mans linq in the pre-linq era wink

That's really cool! I suspected operator overloading, but didn't see any in the VS solution... the partial class declaration didn't have any more parts to it confused and didn't extend any base classes.