3

Suppose I have the two following Linq-To-SQL queries I want to refactor:

var someValue1 = 0;
var someValue2= 0;
var query1 = db.TableAs.Where( a => a.TableBs.Count() > someValue1 )
              .Take( 10 );
var query2 = db.TableAs.Where( a => a.TableBs.First().item1 == someValue2)
              .Take( 10 );

Note that only the Where parameter changes. There is any way to put the query inside a method and pass the Where parameter as an argument?

All the solutions posted in the previous question have been tried and failed in runtime when I try to enumerate the result.

The exception thrown was: "Unsupported overload used for query operator 'Where'"

2 Answers 2

6

Absolutely. You'd write:

public IQueryable<A> First10(Expression<Func<A,bool>> predicate)
{
    return db.TableAs.Where(predicate).Take(10);
}

(That's assuming that TableA is IQueryable<A>.)

Call it with:

var someValue1 = 0;
var someValue2= 0;
var query1 = First10(a => a.TableBs.Count() > someValue1);
var query2 = First10(a => a.TableBs.First().item1 == someValue2);

I believe that will work...

The difference between this and the answers to your previous question is basically that this method takes Expression<Func<T,bool>> instead of just Func<T,bool> so it ends up using Queryable.Where instead of Enumerable.Where.

Sign up to request clarification or add additional context in comments.

1 Comment

Strangr, I tried both cases: Expression<Func<TagFragment, bool>> c1 = t => true; Console.WriteLine(db.Table1.Where(c1).Count()); Func<TagFragment, bool> c2 = t => true; Console.WriteLine(db.Table1.Where(c2).Count()); they gave me the same results, no runtime errors.
1

If you really want reusability you can try to write your own operators. E.g. instead of repeatedly writing:

var query = 
Products
    .Where(p => p.Description.Contains(description))
    .Where(p => p.Discontinued == discontinued);

you can write simple methods:

public static IEnumerable<Product> ByName(this IEnumerable<Product> products, string description)
{
    return products.Where(p => p.Description.Contains(description));
}


public static IEnumerable<Product> AreDiscontinued(IEnumerable<Product> products, bool isDiscontinued)
{
    return products.Where(p => p.Discontinued == discontinued);
}

and then use it like this:

var query = Products.ByName("widget").AreDiscontinued(false);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.