2

string[]の値をテーブルの値に一致させ、一致したテーブルの値を返す単純な linq-to-sql ステートメントがあります。

_tableタイプですSystem.Data.Linq.Table<TEntity>

public IEnumerable<ZipCode> match(IEnumerable<string> values) {
    HashSet<string> valueSet = new HashSet<string>(values);
    return _table.Where(x => valueSet.Contains(x.zipcode);
}

使用するフィールドをに渡すことができるように、これをリファクタリングするにはどうすればよいContains()ですか?

私の失敗した試み:

public IEnumerable<ZipCode> match<T>(IEnumerable<T> values, 
        Expression<Func<ZipCode, T>> field) {
    HashSet<T> valueSet = new HashSet<T>(values);
    return _table.Where(x => valueSet.Contains(field(x)));
}

これにより、次のエラーが発生します。

メソッド 'System.Object DynamicInvoke(System.Object[])' には、サポートされている SQL への変換がありません。

私の考えでは、式ツリーを使用してフィールドを与えることができましたContains()が、これが式を使用する正しい方法であるかどうかについて混乱していました。おそらく全体としてより良い解決策があります。

4

2 に答える 2

2

以下を使用できました(.NET 4.5では、以前のバージョンでも動作すると思います)

static IEnumerable<TTable> Match<TTable, TField>(IQueryable<TTable> table, IEnumerable<TField> values, Expression<Func<TTable, TField>> fieldSelector)
{
    var valuesConstant = Expression.Constant(values.Distinct());

    var callContains = Expression.Call(typeof(Enumerable), "Contains", new[] { typeof(TField) }, new Expression[] { valuesConstant, fieldSelector.Body });

    var whereExpression = Expression.Lambda<Func<TTable, bool>>(callContains, (fieldSelector.Body as MemberExpression).Expression as ParameterExpression);

    return table.Where(whereExpression);
}

私が使用したテーブルパラメータを削除して、あなたが持っているメンバー変数を使用できるはずです。

于 2013-02-06T00:12:28.687 に答える
0

Expression<Func<ZipCode, T>> field使用する代わりにFunc<ZipCode, T> field:

public IEnumerable<ZipCode> match<T>(IEnumerable<T> values, Func<ZipCode, T> field)
{
    HashSet<T> valueSet = new HashSet<T>(values);
    return _table.Where(x => valueSet.Contains(field(x)));
}
于 2013-02-05T15:53:28.027 に答える