Custom predicate filtering with Linq to LLBLGen

Posts   
 
    
cebus2000
User
Posts: 29
Joined: 11-Jan-2006
# Posted on: 10-Feb-2009 23:01:43   

first off, a disclaimer: i am new to Linq. still learning. i've used LLBLGen for years, and i'm excited to combine LL with the new Linq technology.

so. the problem is that in searches, i need to adjust date predicates so that they are actually 'between' filters that encompass all the DateTime values in a particular day. and i want this done in the emitted SQL, NOT in memory. i could do this with a lot of individual predicates, but i'd rather have a generic way to do it. the code for a sample of this is:


static bool AdjustedDateEquals(this DateTime thisVal, DateTime compareVal)
        {
            TimeSpan oneSecond = TimeSpan.FromSeconds(1f);
            DateTime maxDate = compareVal.Date.AddDays(1f).Subtract(oneSecond);
            DateTime minDate = compareVal.Date; //this will be midnight

            return (thisVal >= minDate && thisVal <= maxDate);

        }

now, i have a way to do this inside a Linq query when i know the particular Entity being filtered, and the field to filter on. it generates the correct SQL etc. the prototype looks like:


static IQueryable<MyParticularKindOfEntity> AdjustedDateCreatedEquals(this IQueryable<MyParticularKindOfEntity> sa, DateTime compareVal)

what i want is something vaguely like this:


internal static IQueryable<MyParticularKindOfEntity> AdjustedDateEquals(this IQueryable<MyParticularKindOfEntity> sa, DateTime compareVal, string fieldName)

however, my attempts to do this more generically have failed. the above extension method for DateTime fails with a Query Construction exception, and i can understand why. what i want to do is have a method that accepts an Entity Field and a Value (DateTime), and build a filter that can be added via IQueryable<MyEntity>.Where().

i know that there are simpler ways to do this, but given that i have a lot of different date fields, i don't want to duplicate the same code in many different places. i would greatly prefer to have a single "DateEquals" operator that i can use for all queries that have to use ThisDate=?

again, keeping in mind that i am still learning Linq (and lambda syntax), what's a good generic approach to take to this problem? i have similar problems to address with decimal measurement fields where i need to apply a 'tolerance' to an equality operator.

Thanks much.

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 11-Feb-2009 10:42:43   

Why don't you use DateTime.Value.Day , Month, Year, DayOfYear..etc.

LinqMetaData metaData = new LinqMetaData();
var q = from o in metaData.Order
        [b]where o.OrderDate.Value.Day == xyz[/b]
        select o;
cebus2000
User
Posts: 29
Joined: 11-Jan-2006
# Posted on: 11-Feb-2009 14:53:14   

Sorry, I wasn't really clear- the problem is not restricted to dates, it's just one example (what you suggest will work fine for DateTimes, in most of my cases.) In addition to dates, we have decimal values. In either case, we build in a tolerance value into the filter, along with a comparison operator. Since these kinds of 'fuzzy' comparisons are very common in our solutions, I wanted to move them into a dedicated set of generic extension methods, so they could be easily reused inside any of our Linq queries.

perhaps a better example is with decimals. instead of having to write code like this for every entity with a decimal field:


decimal refValue = 123.45;  //search parameter
decimal lowerBound = refValue - .01m;
decimal upperBound = refValue + .01m;
q = q.Where(x => x.ThicknessMax >= lowerBound && x.ThicknessMax <= upperBound);

i'd want something like this:


decimal refValue = 123.45;  //search parameter
//FuzzyEquals is our own custom comparison with built-in tolerance
q = q.Where(x => x.ThicknessMax.FuzzyEquals(refValue));

Hope that makes more sense, thanks.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 11-Feb-2009 17:47:49   

You can create extension methods for this, though they'll likely not be very easy to write. What your extension method has to do is to produce an Expression based object which represents the filter you'd like to write.

Expression objects have a ToString() method which can be handy during debugging these kind of routines.

Another routine is to create a custom Function mapping, for the sql you'd like to execute. See the Function mapping section in the Linq section in our manual for details.

Frans Bouma | Lead developer LLBLGen Pro
cebus2000
User
Posts: 29
Joined: 11-Jan-2006
# Posted on: 11-Feb-2009 17:50:44   

OK, I understand. Thanks for the info.