LINQ“WhereLike”扩展方法

时间:2012-08-01 18:59:11

标签: c# asp.net linq linq-to-sql

使用LINQ,我需要使用自己的通配符(WHERE LIKE)查询表,我无法使用普通的Contains方法,因为它一直在逃避我的通配符(参见my other question) 。我找到了一个完美无缺的extension method,但仅限于字符串列:

public static IQueryable<T> WhereLike<T>(this IQueryable<T> source, string propertyName, string pattern)
{
    if (null == source) throw new ArgumentNullException("source");
    if (string.IsNullOrEmpty(propertyName)) throw new ArgumentNullException("propertyName");

    var a = Expression.Parameter(typeof(T), "a");
    var prop = Expression.Property(a, propertyName);
    var body = Expression.Call(typeof(SqlMethods), "Like", null, prop, Expression.Constant(pattern));
    var fn = Expression.Lambda<Func<T, bool>>(body, a);

    return source.Where(fn);
}

以下是我如何使用上述方法的示例:

db.TABLE_NAME.WhereLike("COLUMN_NAME", "SEARCH%");

正如我所提到的,这在字符串列上运行得很好,但是当我尝试在非字符串列(例如int)上使用此方法时,它会因错误而崩溃:

No method 'Like' on type 'System.Data.Linq.SqlClient.SqlMethods' is compatible with the supplied arguments.

这是可以理解的,因为您无法对非字符串列执行LIKE操作,您必须先将数据转换或转换为字符串。我对LINQ表达式并不是很熟悉所以我不确定如何修改上面的WhereLike方法来进行强制转换或ToString()。有谁知道我会完成这个,所以我可以在非字符串列上执行通配符搜索?

1 个答案:

答案 0 :(得分:2)

您必须将类型更改为字符串,并L2S supports Object.ToString

为了使用它,您将在另一个方法调用表达式中包装属性访问表达式:

public static IQueryable<T> WhereLike<T>(
    this IQueryable<T> source,
    string propertyName,
    string pattern)
{
    if (null == source)
        throw new ArgumentNullException("source");
    if (string.IsNullOrEmpty(propertyName))
        throw new ArgumentNullException("propertyName");

    var a = Expression.Parameter(typeof(T), "a");

    // Wrap the property access in a call to property.ToString()
    var prop = Expression.Property(a, propertyName);
    var conv = Expression.Call(prop, "ToString", null);

    // Basically: SqlMethods.Like(Convert.ToString([prop]), pattern)
    var body = Expression.Call(
        typeof(SqlMethods), "Like", null,
        conv,
        Expression.Constant(pattern));

    var fn = Expression.Lambda<Func<T, bool>>(body, a);

    return source.Where(fn);
}