20

LINQ-to-Entities を使用して「where in values」タイプの条件を適用する方法を知っている人はいますか? 私は次のことを試しましたが、うまくいきません:

var values = new[] { "String1", "String2" };  // some string values

var foo = model.entitySet.Where(e => values.Contains(e.Name));

これは LINQ-to-SQL でも機能すると思いますか? 何かご意見は?

4

7 に答える 7

19

更新:これを行う方法を見つけました。そして、EF はデータベース上で適切な SQL を生成します。これがEF4専用かどうかはわかりませんが、Entity Framework 4.0 Recipesからヒントを得ました


var listOfIds=GetAListOfIds();
var context=CreateEntityFrameworkObjectContext();
var results = from item in context.Items
              where listOfIds.Contains(item.Category.Id)
              select item;
//results contains the items with matching category Ids

このクエリは、サーバー側で正しい in 句を生成します。EF 3.5 ではテストしていませんが、EF4 では動作します。

注意: in 句に渡される値はパラメーターではないため、入力を検証してください。

于 2008-09-17T23:23:31.653 に答える
1

現時点では、ContainsはEFではサポートされていません。

于 2008-09-18T20:05:02.167 に答える
1

ご参考までに:

ESqlを使用している場合は、運用で使用できます。私は VS 2008 を持っていませんが、コードは次のようになります。

var ids = "12, 34, 35";
using (context = new Entites())
{
    var selectedProducts = context.CreateQuery<Products>(
        String.Format("select value p from [Entities].Products as p 
                       where p.productId in {{{0}}}", ids)).ToList();
    ...
}
于 2010-03-30T07:00:29.703 に答える
1

Containers が Linq to Entities でサポートされていないのは少し残念です。

IN と JOIN は同じ演算子ではありません (IN によるフィルタリングはクエリのカーディナリティを変更しません)。

于 2008-09-18T03:34:30.630 に答える
1

データをクエリするときに式を使用する場合は、次の拡張メソッドを使用できます ( http://social.msdn.microsoft.com/forums/en-US/adodotnetentityframework/thread/095745fe-dcf0- 4142-b684-b7e4a1ab59f0/ ):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Data.Objects;

namespace Sample {
    public static class Extensions {
        public static IQueryable<T> ExtWhereIn<T, TValue>(this ObjectQuery<T> query,
                    Expression<Func<T, TValue>> valueSelector,
                    IEnumerable<TValue> values) {
            return query.Where(BuildContainsExpression<T, TValue>(valueSelector, values));
        }
        public static IQueryable<T> ExtWhereIn<T, TValue>(this IQueryable<T> query,
            Expression<Func<T, TValue>> valueSelector,
            IEnumerable<TValue> values) {
            return query.Where(BuildContainsExpression<T, TValue>(valueSelector, values));
        }
        private static Expression<Func<TElement, bool>> BuildContainsExpression<TElement, TValue>(
                Expression<Func<TElement, TValue>> valueSelector, IEnumerable<TValue> values) {
            if (null == valueSelector) { throw new ArgumentNullException("valueSelector"); }
            if (null == values) { throw new ArgumentNullException("values"); }
            ParameterExpression p = valueSelector.Parameters.Single();
            // p => valueSelector(p) == values[0] || valueSelector(p) == ...
            if (!values.Any()) {
                return e => false;
            }
            var equals = values.Select(value => (Expression)Expression.Equal(valueSelector.Body, Expression.Constant(value, typeof(TValue))));
            var body = equals.Aggregate<Expression>((accumulate, equal) => Expression.Or(accumulate, equal));
            return Expression.Lambda<Func<TElement, bool>>(body, p);
        }
    }
    class Program {
        static void Main(string[] args) {
            List<int> fullList = new List<int>();
            for (int i = 0; i < 20; i++) {
                fullList.Add(i);
            }

            List<int> filter = new List<int>();
            filter.Add(2);
            filter.Add(5);
            filter.Add(10);

            List<int> results = fullList.AsQueryable().ExtWhereIn<int, int>(item => item, filter).ToList();
            foreach (int result in results) {
                Console.WriteLine(result);
            }
        }
    }       
}

拡張機能の使用は非常に簡単です (サンプルでわかるように)。データベース オブジェクトで使用するには、「Product」というテーブルを複数の ID でフィルタリングしていると仮定すると、次のようにすることができます。

class Product {
    public int Id { get; set; }
    /// ... other properties
}


List<Product> GetProducts(List<int> productIds) {    
    using (MyEntities context = new MyEntities()) {
        return context.Products.ExtWhereIn<Product, int>(product => product.Id, productIds).ToList();
    }
}
于 2011-01-21T14:00:22.323 に答える
0

はい、SQL に変換されます。次のような標準の IN ステートメントが生成されます。

SELECT [t0].[col1]
FROM [table] [t0]
WHERE [col1] IN ( 'Value 1', 'Value 2')
于 2008-09-17T22:52:57.670 に答える
0

where メソッドの使用が常に機能するとは限らない

var results = from p in db.Products

             where p.Name == nameTextBox.Text

             select p;
于 2008-09-17T22:54:57.633 に答える