使用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()
。有谁知道我会完成这个,所以我可以在非字符串列上执行通配符搜索?
答案 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);
}