在 T-SQL 中,您可以拥有如下查询:
SELECT * FROM Users WHERE User_Rights IN ("Admin", "User", "Limited")
如何在 LINQ to Entities 查询中复制它?这是否可能?
在 T-SQL 中,您可以拥有如下查询:
SELECT * FROM Users WHERE User_Rights IN ("Admin", "User", "Limited")
如何在 LINQ to Entities 查询中复制它?这是否可能?
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))
在这种情况下,我会选择使用内连接(Inner Join)。如果我使用了 contains 函数,即使只有一个匹配项,它也会迭代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 方法,将在 List 2 中搜索每个 List 1 的元素,这意味着迭代会发生 49 次!!!
var result = _db.Companies.Where(c => _db.CurrentSessionVariableDetails.Select(s => s.CompanyId).Contains(c.Id)).ToList();
我也尝试使用类似于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());
}
}
ObjectQuery<T>.Where
会抛出以下异常:在MSDN论坛中发现了这个问题,可能对您有帮助。期待着下一个版本的.NET和Entity Framework,一切都会变得更好。 :)The argument types 'Edm.Guid' and 'Edm.String' are incompatible for this operation., near equals expression, line 6, column 14.
一种替代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);
}
var selected =
users.Where(u =>
new[] { "Admin", "User", "Limited" }.Intersect(new[] {u.User_Rights}).Any()
);
OR
var selected =
users.Where(u =>
new[] {u.User_Rights}.Intersect(new[] { "Admin", "User", "Limited" }).Any()
);
我想性能应该进行基准测试(与当前接受的答案相比)以完全验证这个解决方案...
正如Gert Arnold所要求的示例(EF 6): 这段代码给我任何名字或姓氏匹配“John”或“Doe”的用户:
// GET: webUsers
public async Task<ActionResult> Index()
{
var searchedNames = new[] { "John", "Doe" };
return
View(
await db
.webUsers
.Where(u => new[] { u.firstName, u.lastName }.Intersect(searchedNames).Any())
.ToListAsync()
);
//return View(await db.webUsers.ToListAsync());
}
真实例子:
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;
查询语法:
string[] month = { "jan", "feb", "mar" };
var qry = from c in populationdata
where c.birthmonth in month
select c;
真的吗?你们从未使用过
where (t.MyTableId == 1 || t.MyTableId == 2 || t.MyTableId == 3)
where new[] { 1, 2, 3 }.Contains(x)
比 where (x == 1 || x == 2 || x == 3)
进行更少的比较吗? - tymtam||
和Contains
的性能是相同的,无论使用多少个||
,而在MS SQL中,性能差异非常大(慢30%?)。我有一种感觉,你关于1000甚至10万行的论点是不正确的。你能支持一下吗? - tymtam