tags:

views:

235

answers:

2

I have a case in my application where the user can search for a list of terms. The search needs to make three passes in the following order:

  • One for an exact match of what they entered. Done, easy.
  • One where all the words (individually) match. Done, also easy.
  • One where any of the words match...how?

Essentially, how do I, in Linq to Sql, tell it to do this:

select * from stuff s where s.Title like '%blah%' || s.Title like '%woo&' || s.Title like '%fghwgads%' || s.Title like...

And so on?

+2  A: 

This might be a tough one... I think you'd have to write your own operator.

(Update: Yep, I tested it, it works.)

public static class QueryExtensions
{
    public static IQueryable<TEntity> LikeAny<TEntity>(
        this IQueryable<TEntity> query,
        Expression<Func<TEntity, string>> selector,
        IEnumerable<string> values)
    {
        if (selector == null)
        {
            throw new ArgumentNullException("selector");
        }
        if (values == null)
        {
            throw new ArgumentNullException("values");
        }
        if (!values.Any())
        {
            return query;
        }
        var p = selector.Parameters.Single();
        var conditions = values.Select(v =>
            (Expression)Expression.Call(typeof(SqlMethods), "Like", null,
                selector.Body, Expression.Constant("%" + v + "%")));
        var body = conditions.Aggregate((acc, c) => Expression.Or(acc, c));
        return query.Where(Expression.Lambda<Func<TEntity, bool>>(body, p));
    }
}

Then you could call this with:

string[] terms = new string[] { "blah", "woo", "fghwgads" };
var results = stuff.LikeAny(s => s.Title, terms);

P.S. You'll need to add the System.Linq.Expressions and System.Data.Linq.SqlClient namespaces to your namespaces for the QueryExtensions class.

Aaronaught
That worked! Thank you!
Dusda
A: 

Thank you so much :)) that worked for me like a charm.. :)

jonny good