4

私はLINQ-To-EntitiesでContainsを実行するために使用している次の拡張メソッドを持っています:

  public static class Extensions
  {    
        public static IQueryable<TEntity> WhereIn<TEntity, TValue>
        (
            this ObjectQuery<TEntity> query,
            Expression<Func<TEntity, TValue>> selector,
            IEnumerable<TValue> collection
        )
        {
            if (selector == null) throw new ArgumentNullException("selector");
            if (collection == null) throw new ArgumentNullException("collection");
            if (!collection.Any())
                return query.Where(t => false);

            ParameterExpression p = selector.Parameters.Single();

            IEnumerable<Expression> equals = collection.Select(value =>
               (Expression)Expression.Equal(selector.Body,
                    Expression.Constant(value, typeof(TValue))));

            Expression body = equals.Aggregate((accumulate, equal) =>
                Expression.Or(accumulate, equal));

            return query.Where(Expression.Lambda<Func<TEntity, bool>>(body, p));
        }

        //Optional - to allow static collection:
        public static IQueryable<TEntity> WhereIn<TEntity, TValue>
          (
            this ObjectQuery<TEntity> query,
            Expression<Func<TEntity, TValue>> selector,
            params TValue[] collection
          )
        {
            return WhereIn(query, selector, (IEnumerable<TValue>)collection);
        }
  }

ID のリストが特定のテーブルにあるかどうかを確認するために拡張メソッドを呼び出すと、機能し、次のように ID のリストが返されます。

List<int> Ids = _context.Persons
                        .WhereIn(x => x.PersonId, PersonIds)
                        .Select(x => x.HeaderId).ToList();

次のステートメントを実行すると、LINQ-To-Entities が Contains(int32) を認識しないと不平を言いますが、もうエンティティに反対するのではなく、int のコレクションだと思っていました。

predicate = predicate.And(x=> Ids.Contains(x.HeaderId));

「1,2,3」などのカンマ区切りの文字列がある場合、次のように機能します。

predicate = predicate.And(x=>x.Ids.Contains(x.HeaderId));

返されたリストを取得して、文字列のカンマ区切りのリストを作成しようとしていますが、ここでの問題は、predicate = predicate.And(x=>sb.Contains(x.HeaderId.ToString());ToString() が好きではないという不平を言うことです。

私もやってみました:

predicate = predicate.And(x=>Extensions.WhereIn(Ids, x.id));, but it can't resolve WhereIn.  It says I must add `<>`, but I am not sure what to add here and how implement it.
4

3 に答える 3

0

WhereInに問題はありません。あなたは正しいです。Idsを使用すると、エンティティに反対することはなくなりますが、int のコレクションになります。

問題は、述語で.Andを使用している場合です。LINQ-To-Entities は、これらのブラケット内のすべてを Entities メソッドに変換しようとしますが、対応するContainsメソッドはありません。

解決:

それ以外の

predicate = predicate.And(x=> Ids.Contains(x.HeaderId));

使用する

predicate = predicate.And(Contains<XClassName, int>(x.HeaderId));

次のように定義されます。

private static Expression<Func<TElement, bool>> Contains<TElement, TValue>(Expression<Func<TElement, TValue>> valueSelector, List<TValue> values)
    {
        if (null == valueSelector) { throw new ArgumentNullException("valueSelector"); }
        if (null == values) { throw new ArgumentNullException("values"); }

        if (!values.Any())
            return e => false;

        var equals = values.Select(value => (Expression)Expression.Equal(valueSelector.Body, Expression.Constant(value, typeof(TValue))));

        return Expression.Lambda<Func<TElement, bool>>(@equals.Aggregate(Expression.Or), valueSelector.Parameters.Single());
    }

XClassName はxのクラスの名前です

于 2013-10-18T19:49:39.063 に答える
-2

あなたを置き換えます:

List<int> Ids = _context.Persons
                    .WhereIn(x => x.PersonId, PersonIds)
                    .Select(x => x.HeaderId).ToList();

var Ids = _context.Persons
                    .WhereIn(x => x.PersonId, PersonIds)
                    .Select(x => x.HeaderId).ToList();

そして試してみてください。

于 2013-05-28T16:37:26.837 に答える