有人知道如何使用 LINQ-to-Entities 应用“值中的位置”类型条件吗?我尝试了以下方法,但它不起作用:
var values = new[] { "String1", "String2" }; // some string values
var foo = model.entitySet.Where(e => values.Contains(e.Name));
我相信这在 LINQ-to-SQL 中有效吗?有什么想法吗?
有人知道如何使用 LINQ-to-Entities 应用“值中的位置”类型条件吗?我尝试了以下方法,但它不起作用:
var values = new[] { "String1", "String2" }; // some string values
var foo = model.entitySet.Where(e => values.Contains(e.Name));
我相信这在 LINQ-to-SQL 中有效吗?有什么想法吗?
更新:找到了如何做到这一点。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 子句的值不是参数,因此请确保验证输入。
Linq to Entities 不支持 Contains有点遗憾。
IN 和 JOIN 不是同一个运算符(按 IN 过滤永远不会改变查询的基数)。
EF 目前不支持包含。
供参考:
如果您使用的是 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();
...
}
对于在查询数据时要使用表达式的情况,可以使用以下扩展方法(改编自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);
}
}
}
}
使用扩展非常简单(如您在示例中所见)。要在数据库对象上使用它,假设您通过多个 id 过滤名为“Product”的表,您可以执行以下操作:
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();
}
}
是的,它确实转换为 SQL,它会生成一个标准的 IN 语句,如下所示:
SELECT [t0].[col1]
FROM [table] [t0]
WHERE [col1] IN ( 'Value 1', 'Value 2')
使用 where 方法并不总是有效
var results = from p in db.Products
where p.Name == nameTextBox.Text
select p;