在T-SQL中,你可以有这样的查询:
SELECT * FROM Users WHERE User_Rights IN ("Admin", "User", "Limited")
如何复制在一个LINQ实体查询?这可能吗?
在T-SQL中,你可以有这样的查询:
SELECT * FROM Users WHERE User_Rights IN ("Admin", "User", "Limited")
如何复制在一个LINQ实体查询?这可能吗?
当前回答
一个替代BenAlabaster回答的方法
首先,你可以像这样重写查询:
var matches = from Users in people
where Users.User_Rights == "Admin" ||
Users.User_Rights == "Users" ||
Users.User_Rights == "Limited"
select Users;
当然,这更“啰嗦”,写起来很痛苦,但它仍然有效。
因此,如果我们有一些实用方法,可以很容易地创建这些LINQ表达式,我们就可以开始工作了。
有了实用工具方法,你可以这样写:
var matches = ctx.People.Where(
BuildOrExpression<People, string>(
p => p.User_Rights, names
)
);
这将构建一个具有相同效果的表达式:
var matches = from p in ctx.People
where names.Contains(p.User_Rights)
select p;
但更重要的是,它实际上适用于。net 3.5 SP1。
下面是管道功能,使这成为可能:
public static Expression<Func<TElement, bool>> BuildOrExpression<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();
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);
}
我不打算解释这个方法,只是说它本质上使用valueSelector(即p => p.User_Rights)为所有值构建一个谓词表达式,并将这些谓词or在一起,为完整的谓词创建一个表达式
来源:http://blogs.msdn.com/b/alexj/archive/2009/03/26/tip-8-writing-where-in-style-queries-using-linq-to-entities.aspx
其他回答
我还尝试使用类似sql - in的东西-查询实体数据模型。我的方法是用一个字符串构建器来组成一个大的or表达式。这太难看了,但恐怕这是目前唯一的办法。
现在看起来是这样的:
Queue<Guid> productIds = new Queue<Guid>(Products.Select(p => p.Key));
if(productIds.Count > 0)
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}.ProductId = Guid\'{1}\'", entities.Products.Name, productIds.Dequeue());
while(productIds.Count > 0)
{
sb.AppendFormat(" OR {0}.ProductId = Guid\'{1}\'",
entities.Products.Name, productIds.Dequeue());
}
}
在这个上下文中使用GUID:正如您在上面看到的,在查询字符串片段中,GUID本身之前总是有单词“GUID”。如果不添加,ObjectQuery<T>。Where抛出以下异常:
参数类型为Edm。Guid”和 的电火花。字符串`不兼容 操作。,近似等于表达式, 第6行14列。
在MSDN论坛上找到了这个,可能会有帮助。
Matthias
... 期待下一个版本的。net和实体框架,当一切都变得更好。:)
严重吗?你们从没用过
where (t.MyTableId == 1 || t.MyTableId == 2 || t.MyTableId == 3)
这可能是直接使用LINQ扩展方法检查in子句的可能方式
var result = _db.Companies.Where(c => _db.CurrentSessionVariableDetails.Select(s => s.CompanyId).Contains(c.Id)).ToList();
这应该够你的目的了。它比较两个集合,并检查其中一个集合的值是否与另一个集合中的值匹配
fea_Features.Where(s => selectedFeatures.Contains(s.feaId))
一个替代BenAlabaster回答的方法
首先,你可以像这样重写查询:
var matches = from Users in people
where Users.User_Rights == "Admin" ||
Users.User_Rights == "Users" ||
Users.User_Rights == "Limited"
select Users;
当然,这更“啰嗦”,写起来很痛苦,但它仍然有效。
因此,如果我们有一些实用方法,可以很容易地创建这些LINQ表达式,我们就可以开始工作了。
有了实用工具方法,你可以这样写:
var matches = ctx.People.Where(
BuildOrExpression<People, string>(
p => p.User_Rights, names
)
);
这将构建一个具有相同效果的表达式:
var matches = from p in ctx.People
where names.Contains(p.User_Rights)
select p;
但更重要的是,它实际上适用于。net 3.5 SP1。
下面是管道功能,使这成为可能:
public static Expression<Func<TElement, bool>> BuildOrExpression<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();
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);
}
我不打算解释这个方法,只是说它本质上使用valueSelector(即p => p.User_Rights)为所有值构建一个谓词表达式,并将这些谓词or在一起,为完整的谓词创建一个表达式
来源:http://blogs.msdn.com/b/alexj/archive/2009/03/26/tip-8-writing-where-in-style-queries-using-linq-to-entities.aspx