Code sharing options in Linq2SQL expressions

I have a couple of Linq to SQL queries that contain the same Where clause, specifically:

where ((range.MinimumFrequency <= minFreq &&  minFreq <= range.MaximumFrequency)
|| (range.MinimumFrequency <= maxFreq && maxFreq <= range.MaximumFrequency)
|| (range.MinimumFrequency <= minFreq && maxFreq <= range.MaximumFrequency)
|| (range.MinimumFrequency >= minFreq && maxFreq >= range.MaximumFrequency))

      

And instead of copying and pasting this piece of code all over the place, I would like to refactor it into something else that can be used. I know I cannot do this with the normal method as it cannot be translated to SQL, but I also cannot get

Expression <Func <... →

things described here to work.

If I am simplifying the where clause for my convenience here, I want to rotate

where (range.MinumumFrequency < minFreq) 

      

into an expression, so I tried:

public static Expression<Func<FreqRange, bool>> Overlaps(decimal minMHz, decimal maxMHz)
{
   return (range => range.MinimumFrequency <= minMHz);
}

      

It looks like compilation, but I can't get the where clause to work, I tried the following:

where FreqRange.Overlaps(minMHz, maxMHz)

      

but this gives me a compile time error:

Cannot implicitly convert type 'System.Linq.Expressions.Expression>' to 'bool'

Any ideas? Also, assuming we get this working, can I just extend the lambda expression in <Func <→ to include other conditions?

+2


source to share


2 answers


If you are using LINQ syntax with language construction, you are implicitly declaring a lamba expression - and that lamba expression is Expression<Func <>>

- so you don't need a where clause to return an expression, you need an expression.

eg.

var q = from row in myTable
        where row.a < aMax
        select row.b;

// which translates to

var q = myTable.Where(row => row.a < aMax).Select(row => row.b);

      

Now you need to "cache" row => row.a < aMax

, not just the value row.a < aMax

, if you like. So, if you were writing something like this ...

Expression<Func<?,bool>> cachedExpression = row => row.a < aMax;

var q = from row in myTable
        where cachedExpression
        select row.b;

      



Well, you say "where, given the row, it's true that (given the row, it's true that row.a is less than aMax)". This is nonsense and won't compile if cachedExpression is of type Expression<Func<?,bool>>

and myTable is a LinqToSql table. This will translate something like this:

Expression<Func<?,bool>> cachedExpression = row => row.a < aMax;

//nonsense .Where:
var q = myTable.Where(row => cachedExpression).Select(row => row.b);
//effectively says this:
var q = myTable.Where(row => (row0 => row0.a < aMax)).Select(row => row.b);

      

This is now legal in the sense that the linq query provider can implement whereclause with a non-boolean value, but this is very strange; Of course, no standard linq providers (such as Linq to Sql) do this.

So what should you do? Something like:

//not .Where(row=>cachedExpression)!
var q = myTable.Where(cachedExpression).Select(row => row.b);

//or, alternatively:
var q = from filteredRow in myTable.Where(cachedExpression)
        select filteredRow.b;

      

+2


source


You can also create a method that accepts and dispatches an IQueryable. I've used these views, but only in code.

public class WithProps
{
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
    public override string ToString()
    {
        return string.Format("{0}-{1}", Prop1, Prop2);
    }
}

public static class Tools
{
    public static IQueryable<WithProps> MyFilter(this IQueryable<WithProps> props)
    {
        return props.Where(p => p.Prop1 == "hi");
    }
}

class Program
{
    static void Main(string[] args)
    {
        var propList = new List<WithProps>()
        {
            new WithProps(){ Prop1="hi", Prop2="there"},
            new WithProps(){ Prop1="hi", Prop2="bye"},
            new WithProps(){ Prop1="hello", Prop2="world"},
            new WithProps(){ Prop1="bye", Prop2="friend"}
        };

        var filtered = propList.AsQueryable().MyFilter();

        Console.WriteLine("propList ===");
        foreach (var item in propList)
            Console.WriteLine(item.ToString());
        Console.WriteLine("filtered ===");
        foreach (var item in filtered)
            Console.WriteLine(item.ToString());
    }
}

      



... Results...

propList ===
hi-there
hi-bye
hello-world
bye-friend
filtered ===
hi-there
hi-bye

      

+1


source







All Articles