简体   繁体   中英

Converting a Linq expression tree that relies on SqlMethods.Like() for use with the Entity Framework

I recently switched from using Linq to Sql to the Entity Framework. One of the things that I've been really struggling with is getting a general purpose IQueryable extension method that was built for Linq to Sql to work with the Entity Framework. This extension method has a dependency on the Like() method of SqlMethods, which is Linq to Sql specific. What I really like about this extension method is that it allows me to dynamically construct a Sql Like statement on any object at runtime, by simply passing in a property name (as string) and a query clause (also as string). Such an extension method is very convenient for using grids like flexigrid or jqgrid. Here is the Linq to Sql version (taken from this tutorial: http://www.codeproject.com/KB/aspnet/MVCFlexigrid.aspx ):

    public static IQueryable<T> Like<T>(this IQueryable<T> source,
                  string propertyName, string keyword)
    {
        var type = typeof(T);
        var property = type.GetProperty(propertyName);
        var parameter = Expression.Parameter(type, "p");
        var propertyAccess = Expression.MakeMemberAccess(parameter, property);
        var constant = Expression.Constant("%" + keyword + "%");
        var like = typeof(SqlMethods).GetMethod("Like",
                   new Type[] { typeof(string), typeof(string) });
        MethodCallExpression methodExp =
              Expression.Call(null, like, propertyAccess, constant);
        Expression<Func<T, bool>> lambda =
              Expression.Lambda<Func<T, bool>>(methodExp, parameter);
        return source.Where(lambda);
    }

With this extension method, I can simply do the following:

someList.Like("FirstName", "mike");

or

anotherList.Like("ProductName", "widget");

Is there an equivalent way to do this with Entity Framework?

Thanks in advance.

The SQL method PATINDEX provides the same functionality as LIKE. Therefore, you can use the SqlFunctions.PatIndex method.

.Where(x => SqlFunctions.PatIndex("%123%ABC", x.MySearchField) > 0)

or

var miSqlPatIndex = typeof(SqlFunctions).GetMethod(
    "PatIndex", 
    BindingFlags.Public | BindingFlags.Static | BindingFlags.IgnoreCase, 
    null, 
    new Type[] { typeof(string), typeof(string) }, 
    null);                        
expr = Expression.GreaterThan(
    Expression.Call(
        miSqlPatIndex, 
        new Expression[] { Expression.Constant("%123%ABC"), MySearchField }),
        Expression.Convert(Expression.Constant(0), typeof(int?)));

I was able to find a good solution here: http://www.codeproject.com/KB/aspnet/AspNetMVCandJqGrid.aspx

It essentially uses the "Contains" method of the string class instead of the Like method of the SqlMethods class.

Expression condition = Expression.Call(memberAccess, typeof(string).GetMethod("Contains"), Expression.Constant(keyword));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM