Using dynamically created predicates

Posts   
 
    
maf123sp
User
Posts: 26
Joined: 09-Jan-2013
# Posted on: 05-Jun-2013 15:09:59   

Hi all,

I have a proble, where I'm really lost. Probably there is an easy solutuion, but I can't see it so far.

We have our own - very old - expressions and want to convert those into such construct, that we can use it in a Linq Where clause like this

var exp = OurExpression

"from a in m_LinqMetaData.Table Where(exp) select a"

So far I have converted all our expressions into PredicateExpressions:

var fieldName = "AnyFieldName"; var field = new EntityField(fieldName, (IExpression) null); var pexp = new PredicateExpression(new FieldCompareValuePredicate(field, ComparisonOperator.Equal, any_value));

The final piece is the mystery part for me - how can I convert the Predicateexpression into such an statement, that I can use it in the Wher clause. I also have implemented my own Where which is based on Expression, but both classes - also when they are named similiar - are not derived from each other.

For several reason I'm focusing on a Linq based solution.

There is no knowledge about the fieldName during compile time. The DynamicLinq approach works fine, but there is no support for several functions I need. The PredicateBuilder is here not helpful.

Thanks for any help,

Matthias

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 05-Jun-2013 18:37:08   

The DynamicLinq approach works fine, but there is no support for several functions I need. The PredicateBuilder is here not helpful.

Which functions are you missing? And why PredicateBuilder is not helpful?

maf123sp
User
Posts: 26
Joined: 09-Jan-2013
# Posted on: 05-Jun-2013 19:31:35   

IN DynamicLinq I miss

Like CaseINsensitive Equal and CaseInsesitive Like.

From my understanding teh PredicateBuilder is helpful in combining Predicates (Or, And, ...) This is a problem already solved via Expression.And ...

My prefered way would be DynamicLinq (such apporach was already implemeneted an tested - bu I've stopped since missing Like ...)

Thanks

Matthias

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 06-Jun-2013 08:11:06   

Hi Matthias,

In Linq, you can make insensitive comparison using ToUpper, for instance:

var q = from c in metaData.Customer
            where c.Country.ToUpper() == someValue.ToUper()
             ...

... or sensitive:

var q = from c in metaData.Customer
            where c.Country == someValue
             ...

Then you can use PredicateBuilder in the same way... Does that make sense for you?

David Elizondo | LLBLGen Support Team
maf123sp
User
Posts: 26
Joined: 09-Jan-2013
# Posted on: 06-Jun-2013 09:23:20   

I know, but I cannot use this construct. I dont have the field names at compile time. I used

var field = new EntityField(fieldName, (IExpression) null); field = new EntityField(null, StringFunctions.ToUpper(fieldName)); new PredicateExpression(new FieldCompareValuePredicate(field, ComparisonOperator.Equal, value)); (so far untested)

instead. In DynamicLinq I could build the query with .Where("ToUpper(FieldName)==ToUpper(\"Test\"") (tested)

But I miss the Like in DynamicLinq. Our customers use "like" operations a lot. All queries are case insensitive. The DB schema is (some tables) generic to have a high level of customization.

Thanks

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 06-Jun-2013 20:43:34   

And what's the issue with using LLBLGen Pro's query APIs. instead of the Linq constructs?

maf123sp
User
Posts: 26
Joined: 09-Jan-2013
# Posted on: 07-Jun-2013 07:19:40   

As I said - it might be, that I'm blind for the easiest approach...

I would prefer Linq, since a lot of queries do not need a complete load of the full stream. From my understanding the Fetch methods always load the whole stream from the db.

My current problem is, how to combine the IPredicateExpression objects and a linq "where" statement.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 07-Jun-2013 08:56:02   

In theory that is possible. See the class PredicateBuilder, it has some Reflection tricks on the date comparison. You should do something similar, maybe by extending the PredicateBuilder.

Otherwise, my recommendation is to move to LLBLGen API, as you are doing something very generic. A tip for creating a EntityField2 object from just entityName and fieldName:

EntityField2 field = (EntityField2) EntityFieldFactory.Create(entityName, fieldName);
David Elizondo | LLBLGen Support Team
maf123sp
User
Posts: 26
Joined: 09-Jan-2013
# Posted on: 14-Jun-2013 13:28:49   

Coming back to my problem ...

Thanks so far:

I'm having still the same problem. Here is a code snipped out of the DynamicLinq package

    public static IQueryable Where(this IQueryable source, System.Linq.Expressions.Expression predicate)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (predicate == null) throw new ArgumentNullException("predicate");
        return source.Provider.CreateQuery(System.Linq.Expressions.Expression.Call(typeof(Queryable), "Where", new Type[] { source.ElementType }, source.Expression, System.Linq.Expressions.Expression.Quote(predicate)));
    }

I need a solution, with the following declaratuion: public static IQueryable<T> Where<T>(this IQueryable<T> source, IPredicateExpression predicate) { ??? }

Alternativly I need a conversion IPredicateExpression -->System.Linq.Expressions.Expression predicate

Any help is really appreciated.

Thanks a lot,

Matthias

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 17-Jun-2013 09:16:52   

Dynamic Linq is a subset of Linq, it works by converting strings to Expression<Func<>> and method calls, but it's far from complete.

Why not use queryspec? You can append the predicate to a query with 1 method call: query.Where(predicate).

Frans Bouma | Lead developer LLBLGen Pro
maf123sp
User
Posts: 26
Joined: 09-Jan-2013
# Posted on: 17-Jun-2013 13:38:55   

I'm sorry - this answer was not really helpful, since that's, what I'm looking for.

I have an PredicateExpression (LLBL) and want to use it in a Where clause.

Is there any working approach?

Thanks a lot,

Matthias

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 17-Jun-2013 19:35:00   

I think Frans' suggestion to opt for QuerySpec is the best option for your case.

More about QuerySpec:

The goal for the QuerySpec API is to make it easier to use our native Query API by using a fluent interface which mimics the SQL query to produce. This is close to the native query api which embodies the SQL query fragments at a lower level. It's not a replacement for our Linq provider, it should be seen as an alternative to our linq provider which is as expressive and simple to use as the Linq provider. It also lets you write queries close to SQL's own structure, which can help people who find Linq's structure awkward.

So the advantage here is that it has APIs that accepts an IPredicate as explained above.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 18-Jun-2013 10:18:08   

Indeed. It's not possible to append a predicate to a linq query, simply because in linq queries everything is always aliased, but inside the predicate you don't know the alias to reference so it will never work.

In queryspec this is different as it works with our native api elements. What I find a bit odd is that you try to append a predicate to a linq query: if you dynamically create the predicate, try to create it dynamically with the predicate builder http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=14224 , otherwise it's not possible (which is actually Linq's 'fault', as it's the way a linq query is specified at runtime (in an expression tree with sequences) which requires a transformation to SQL, and isn't 1:1 mappable to the low-level api (and thus also not to sql))

Frans Bouma | Lead developer LLBLGen Pro