0

使用 LINQ,我需要使用自己的通配符(WHERE LIKE)查询表,但我不能使用普通Contains方法,因为它一直在转义我的通配符(请参阅我的其他问题)。我发现了一种可以完美运行的扩展方法,但仅适用于字符串列:

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()先进行转换。有谁知道我会做到这一点,所以我可以在非字符串列上执行通配符搜索?

4

2 回答 2

2

您必须将类型更改为字符串,并且L2S 支持 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);
}
于 2012-08-01T20:01:53.963 回答
0

也许您可以将最后一行更改为:

return source.Select(t => t.ToString()).Where(fn); 

编辑:

这是您在我发表评论后尝试的吗?

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(string), "a");
  var prop = Expression.Property(a, propertyName);
  var body = Expression.Call(typeof(SqlMethods), "Like", null, prop, Expression.Constant(pattern));
  var fn = Expression.Lambda<Func<string, bool>>(body, a);

  return source.Select(t => t.ToString()).Where(fn);
} 
于 2012-08-01T19:03:04.143 回答