6

エンティティへの linq では、"sql like" のように機能するメソッドが必要でした。「%a%b%」のようなパターンを受け入れないため、contains メソッドが機能しないため、IQueryable に独自の拡張メソッドを実装しました。

作成したコードは次のとおりです。

private const char WildcardCharacter = '%';

public static IQueryable<TSource> WhereLike<TSource>(this IQueryable<TSource> _source, Expression<Func<TSource, string>> _valueSelector, string _textSearch)
{
    if (_valueSelector == null)
    {
        throw new ArgumentNullException("valueSelector");
    }

        return _source.Where(BuildLikeExpressionWithWildcards(_valueSelector, _textSearch));
}

private static Expression<Func<TSource, bool>> BuildLikeExpressionWithWildcards<TSource>(Expression<Func<TSource, string>> _valueSelector, string _textToSearch)
{
    var method = GetPatIndexMethod();

    var body = Expression.Call(method, Expression.Constant(WildcardCharacter + _textToSearch + WildcardCharacter), _valueSelector.Body);

    var parameter = _valueSelector.Parameters.Single();
    UnaryExpression expressionConvert = Expression.Convert(Expression.Constant(0), typeof(int?));
    return Expression.Lambda<Func<TSource, bool>> (Expression.GreaterThan(body, expressionConvert), parameter);
}

private static MethodInfo GetPatIndexMethod()
{
    var methodName = "PatIndex";

    Type stringType = typeof(SqlFunctions);
    return stringType.GetMethod(methodName);
}

これは正しく機能し、コードは完全に SqlServer で実行されますが、この拡張メソッドを where 句内で次のように使用します。

myDBContext.MyObject.Where(o => o.Description.Like(patternToSearch) || o.Title.Like(patterToSerch));

問題は、where 句で使用されるメソッドが、'||' のような演算子と共に使用される場合、bool の結果を返さなければならないことです。、作成したコードがブール値を返し、コードを sqlserver で実行したままにする方法がわかりません。BuildLinqExpression メソッドで返された Expression を bool に変換する必要があると思いますが、その方法がわかりません。

総括する!まず、Linq で独自の拡張メソッドを作成して、SqlServer でコードを実行するエンティティを作成することは可能ですか? これが可能な場合、どうすればよいですか?

ご協力いただきありがとうございます。

4

2 に答える 2

3

いいえ、EFで使用できる式作成するコードがある場合でも、カスタム拡張メソッドを処理するようにEFを教育することはできません。

また:

  • SqlFunctionsEFWhere式で直接メソッドを使用する
  • を使用しExpressionVisitorて、複数の式を複合(OrElse/ AndAlso)式に結合します(これは、希望するコードを作成するのに役立ちませんが、2つのメソッドを使用して||、それらに対してを実行できます-複雑に見えます)

1つ目は、より単純で明確です。

于 2012-05-23T10:52:02.940 に答える
2

ここで回答: https://stackoverflow.com/a/10726256/84206

彼のコード: http://pastebin.com/4fMjaCMV

拡張メソッドにタグを付けることができ[Expandable]、それが返す式が linq2entities で機能する限り、関数呼び出しが内部式に置き換えられます。インライン ラムダではエラーが発生することに注意してください。そのため、ローカル変数または次の変数のような静的変数として宣言する必要がありましIsCurrentた。

static Expression<Func<PropertyHistory, bool>> IsCurrent = (p) => p.Starts <= DateTime.Now;

[ExpandableMethod]
public static IQueryable<PropertyHistory> AsOf(this IQueryable<PropertyHistory> source)
{
  return source.Where(IsCurrent);
}
于 2012-06-05T17:28:53.327 に答える