3

I've got two IQueryables:

    public static IQueryable<Counterparty> SearchByCode(this IQueryable<Counterparty> queryable, string searchQuery)
    {
        return queryable.Where(x => x.Code.StartsWith(searchQuery.ToUpper()));
    }

    public static IQueryable<Counterparty> SearchByName(this IQueryable<Counterparty> queryable, string searchQuery)
    {
        return queryable.Where(x => x.Name.ToLower().Contains(searchQuery.ToLower()));
    }

I want to create another IQueryable which combines the two queries as an OR e.g

    public static IQueryable<Counterparty> SearchByCodeOrName(this IQueryable<Counterparty> queryable, string searchQuery)
    {
        // return SearchByName(searchQuery) OR SearchByCode(searchQuery)
    }

I'd rather avoid duplication of code so I want to reuse the existing queryables rather than rewriting a new lambda expression like Where(x=> x.Code.StartsWith.... || x.Name.Contains.....)

reach4thelasers
  • 26,181
  • 22
  • 92
  • 123

2 Answers2

5

You can probably .Union the results of the two together

public static IQueryable<Counterparty> SearchByCodeOrName(this IQueryable<Counterparty> queryable, string searchQuery)
{
     return SearchByName(searchQuery).Union(SearchByCode(searchQuery))
}
Oblivion2000
  • 616
  • 4
  • 9
  • Definitely the neatest approach but I'm not sure if this will cause two roundtrips to the database in Entity Framework or not... – reach4thelasers May 09 '12 at 08:26
1

Depending on what code you do want to be able to reuse, this could be an alternative way of doing it where you are not duplicating the inner workings of your query conditions:

    private static Func<Counterparty, string, bool> CodeStartsWith = (x, searchQuery) => x.Code.StartsWith(searchQuery.ToUpper());

    private static Func<Counterparty, string, bool> NameContains = (x, searchQuery) => x.Name.Contains(searchQuery.ToLower());

    public static IQueryable<Counterparty> SearchByCode(this IQueryable<Counterparty> queryable, string searchQuery)
    { 
        return queryable.Where(x => CodeStartsWith(x, searchQuery)); 
    }

    public static IQueryable<Counterparty> SearchByName(this IQueryable<Counterparty> queryable, string searchQuery)
    {
        return queryable.Where(x => NameContains(x, searchQuery)); 
    }

    public static IQueryable<Counterparty> SearchByCodeOrName(this IQueryable<Counterparty> queryable, string searchQuery)
    {
        return queryable.Where(x => NameContains(x, searchQuery) || CodeStartsWith(x, searchQuery)); 
    }
Ulf Åkerstedt
  • 3,086
  • 4
  • 26
  • 28
  • 1
    This is actually The method I came up with myself! Good answer! – reach4thelasers May 09 '12 at 08:26
  • @reach4thelasers: You should perhaps check out [the Albaharis' PredicateBuilder](http://www.albahari.com/nutshell/predicatebuilder.aspx) and [this EF/ORM friendly version](http://petemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder/) and [the latter's linked explanation](http://blogs.msdn.com/b/meek/archive/2008/05/02/linq-to-entities-combining-predicates.aspx) about how to solve the question problem using Expressions. :-) – Ulf Åkerstedt Mar 12 '14 at 15:43