2008-09-17 5 views
20

Кто-нибудь знает, как применить условие типа «где в значениях» с использованием LINQ-to-Entities? Я пробовал следующее, но это не работает:Как сделать «где в значениях» в LINQ-to-Entities 3.5

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

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

Я считаю, что это работает в LINQ-to-SQL? Есть предположения?

+0

Связанный: http://stackoverflow.com/questions/6994730/how-to-workaround-contains-for-net-3-5-dont-support – 2012-03-05 18:46:39

ответ

0

Да это перевести на SQL, он генерирует стандарт в заявлении, как это:.

SELECT [t0] [col1] FROM [таблица] [t0] WHERE [col1] IN («Значение 1 », 'Value 2')

+0

При использовании LINQ-to-Entities ala ADO.NET Entity Framework я получаю исключение, поскольку «Содержит» не может быть переведено , Я знаю, что он должен перевести, но он не работает. – 2008-09-17 23:02:46

0

Использование где метод не работает непрестанно

var results = from p in db.Products 

      where p.Name == nameTextBox.Text 

      select p; 
+0

Спасибо, Гейб. Я знаю альтернативный синтаксис LINQ, и он работает точно так же. Мой вопрос здесь в том, как делать условия типа «где в значениях». – 2008-09-17 22:58:42

19

Update: узнал, как это сделать. И EF будет генерировать соответствующий SQL в базе данных. Я не уверен, если это только EF4, но я получил совет от Entity Framework 4.0 Рецепты


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 

Этот запрос генерирует правильный в пункте на стороне сервера. Я не тестировал его с EF 3.5, но он работает с EF4.

NB: Значения, переданные в раздел in, не являются параметрами, поэтому убедитесь, что вы проверяете свои входы.

+0

Спасибо, Майк, ты чемпион. – 2008-09-18 00:00:48

+0

Спасибо за дополнение! – 2008-09-18 02:22:21

1

FYI:

Если вы используете 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(); 
    ... 
} 
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); 
      } 
     } 
    }  
} 

Использование расширений очень просто (как вы можете видеть в примере). Для того, чтобы использовать его на объект базы данных, если вы фильтруются таблицу под названием «Продукт» более одного идентификатора, вы могли бы сделать что-то вроде этого:

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(); 
    } 
}