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 に答える