JN
less than a minute read

Generic IQueryable 'OR' search for multiple search terms using expression trees

#generics#expression-trees#lambda#linq#extension-methods#search#sql#csharp#search-extensions

Now available as a nuget package. Search for 'SearchExtensions' or run the following:

<p class="nuget-badge"><code>PM> Install-Package NinjaNye.SearchExtensions</code></p> **Source code can be found here: [https://github.com/ninjanye/searchextensions](https://github.com/ninjanye/searchextensions)**

Continuing my latest theme of search extension methods, my new method allows users to search a property against multiple search terms.

The code has been added to my existing search extensions project which can be found on github by going to https://github.com/ninjanye/SearchExtensions

public static class QueryableExtensions
{
    public static IQueryable<T> Search<T>(this IQueryable<T> source, 
                                          Expression<Func<T, string>> stringProperty, 
                                          params string[] searchTerms)
    {
        if (!searchTerms.Any())
        {
            return source;
        }

        Expression orExpression = null;
        foreach (var searchTerm in searchTerms)
        {
            //Create expression to represent x.[property].Contains(searchTerm)
            var searchTermExpression = Expression.Constant(searchTerm);
            var containsExpression = BuildContainsExpression(stringProperty, searchTermExpression);

            orExpression = BuildOrExpression(orExpression, containsExpression);
        }

        var completeExpression = Expression.Lambda<Func<T, bool>>(orExpression, stringProperty.Parameters);
        return source.Where(completeExpression);
    }

    private static Expression BuildOrExpression(Expression existingExpression, Expression expressionToAdd)
    {
        if (existingExpression == null)
        {
            return expressionToAdd;
        }

        //Build 'OR' expression for each property
        return Expression.OrElse(existingExpression, expressionToAdd);
    }
}

This allows the following linq statement:

var users = context.Users.Search(u => u.UserName, "john", "bob", "fred");

... which, if used via entity framework against a SQL database converts to the following SQL

SELECT [Extent1].[Id] AS [Id],   
       [Extent1].[UserName] AS [UserName],   
       [Extent1].[FirstName] AS [FirstName],   
       [Extent1].[LastName] AS [LastName],   
       [Extent1].[Email] AS [Email],   
FROM   [dbo].[Users] AS [Extent1]  
WHERE ([Extent1].[UserName] LIKE N'%john%')   
   OR ([Extent1].[UserName] LIKE N'%bob%')   
   OR ([Extent1].[UserName] LIKE N'%fred%')

Leave a comment