Answers:
您需要根据考虑的方式将其翻转。您不是要“输入”以在一组预定义的适用用户权限中查找当前项目的用户权限,而是要询问一组预定义的用户权限是否包含当前项目的适用值。这与在.NET的常规列表中找到项目的方式完全相同。
有两种使用LINQ进行此操作的方法,一种使用查询语法,另一种使用方法语法。本质上,它们是相同的,可以根据您的喜好互换使用:
查询语法:
var selected = from u in users
where new[] { "Admin", "User", "Limited" }.Contains(u.User_Rights)
select u
foreach(user u in selected)
{
//Do your stuff on each selected user;
}
方法语法:
var selected = users.Where(u => new[] { "Admin", "User", "Limited" }.Contains(u.User_Rights));
foreach(user u in selected)
{
//Do stuff on each selected user;
}
在这种情况下,我个人的喜好可能是方法语法,因为不用分配变量,我可以对匿名调用执行foreach,如下所示:
foreach(User u in users.Where(u => new [] { "Admin", "User", "Limited" }.Contains(u.User_Rights)))
{
//Do stuff on each selected user;
}
从语法上看,这看起来更复杂,并且您必须了解lambda表达式或委托的概念才能真正弄清楚发生了什么,但是如您所见,这使代码浓缩了很多。
一切都取决于您的编码风格和偏好-我的三个示例在做同一件事时都略有不同。
另一种方法甚至不使用LINQ,您可以使用相同的方法语法将“ where”替换为“ FindAll”,并获得相同的结果,这在.NET 2.0中也适用:
foreach(User u in users.FindAll(u => new [] { "Admin", "User", "Limited" }.Contains(u.User_Rights)))
{
//Do stuff on each selected user;
}
这应该足以满足您的目的。它比较两个集合,并检查一个集合的值是否与另一个集合的值匹配
fea_Features.Where(s => selectedFeatures.Contains(s.feaId))
如果您使用的是VS2008 / .net 3.5,请参阅Alex James的提示#8: http //blogs.msdn.com/alexj/archive/2009/03/26/tip-8-writing-where-in-style使用linq-to-entities.aspx查询
否则,只需使用array.Contains(someEntity.Member)方法。
在这种情况下,我将参加内部联接。如果我使用过包含,那么即使只有一场比赛,它也会迭代6次。
var desiredNames = new[] { "Pankaj", "Garg" };
var people = new[]
{
new { FirstName="Pankaj", Surname="Garg" },
new { FirstName="Marc", Surname="Gravell" },
new { FirstName="Jeff", Surname="Atwood" }
};
var records = (from p in people join filtered in desiredNames on p.FirstName equals filtered select p.FirstName).ToList();
假设我有两个列表对象。
List 1 List 2
1 12
2 7
3 8
4 98
5 9
6 10
7 6
使用Contains,它将搜索列表2中的每个列表1项目,这意味着迭代将发生49次!
我还尝试使用类似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”和“ Edm.String”对此操作不兼容。在等号表达式的第6行第14列第14行。
在MSDN论坛中发现了这一点,可能对您有所帮助。
马蒂亚斯
...一切都会好起来的时候,我们期待下一个.NET和Entity Framework的下一个版本。:)
BenAlabaster答案的替代方法
首先,您可以像这样重写查询:
var matches = from Users in people
where Users.User_Rights == "Admin" ||
Users.User_Rights == "Users" ||
Users.User_Rights == "Limited"
select Users;
当然,这更“罗word”,而且写起来很痛苦,但它的作用相同。
因此,如果我们有一些实用的方法可以很容易地创建此类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
真实的例子:
var trackList = Model.TrackingHistory.GroupBy(x => x.ShipmentStatusId).Select(x => x.Last()).Reverse();
List<int> done_step1 = new List<int>() {2,3,4,5,6,7,8,9,10,11,14,18,21,22,23,24,25,26 };
bool isExists = trackList.Where(x => done_step1.Contains(x.ShipmentStatusId.Value)).FirstOrDefault() != null;
认真吗 你们从未用过
where (t.MyTableId == 1 || t.MyTableId == 2 || t.MyTableId == 3)
Checks = NumValues * NumRows
。因为这是M * N类型的计算,所以如果其中一个很小,那么执行每个所需检查的时间也将很小。我添加了约束,因此cjm30305将知道如何设置测试环境,以显示其解决方案不好的原因。
where new[] { 1, 2, 3 }.Contains(x)
比较少where (x == 1 || x == 2 || x == 3)
吗?