Linq to Entities - SQL“IN” 条款
在 T-SQL 中,您可以有这样的查询:
SELECT * FROM Users WHERE User_Rights IN ("Admin", "User", "Limited")
如何在 LINQ to Entities 查询中复制该查询? 有可能吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
你需要彻底改变你的思考方式。 您不是通过“in”在一组预定义的适用用户权限中查找当前项目的用户权限,而是询问一组预定义的用户权限是否包含当前项目的适用值。 这与在 .NET 的常规列表中查找项目的方式完全相同。
使用 LINQ 有两种方法可以执行此操作,一种使用查询语法,另一种使用方法语法。 本质上,它们是相同的,并且可以根据您的偏好互换使用:
查询语法:
方法语法:
因为我可以通过匿名调用执行 foreach,如下所示:
在这种情况下,我个人的偏好可能是方法语法, 知道发生了什么,但正如您所看到的,这大大压缩了代码。
这一切都取决于您的编码风格和偏好 - 我的所有三个示例都以略有不同的方式执行相同的操作。
另一种方法甚至不使用 LINQ,您可以使用相同的方法语法将“where”替换为“FindAll”并获得相同的结果,这也适用于 .NET 2.0:
You need to turn it on its head in terms of the way you're thinking about it. Instead of doing "in" to find the current item's user rights in a predefined set of applicable user rights, you're asking a predefined set of user rights if it contains the current item's applicable value. This is exactly the same way you would find an item in a regular list in .NET.
There are two ways of doing this using LINQ, one uses query syntax and the other uses method syntax. Essentially, they are the same and could be used interchangeably depending on your preference:
Query Syntax:
Method Syntax:
My personal preference in this instance might be method syntax because instead of assigning the variable, I could do the foreach over an anonymous call like this:
Syntactically this looks more complex, and you have to understand the concept of lambda expressions or delegates to really figure out what's going on, but as you can see, this condenses the code a fair amount.
It all comes down to your coding style and preference - all three of my examples do the same thing slightly differently.
An alternative way doesn't even use LINQ, you can use the same method syntax replacing "where" with "FindAll" and get the same result, which will also work in .NET 2.0:
这应该足以满足您的目的。 它比较两个集合并检查一个集合是否具有与另一集合中的值匹配的值
This should suffice your purpose. It compares two collections and checks if one collection has the values matching those in the other collection
在这种情况下我将选择内部连接。 如果我使用 contains,它会迭代 6 次,尽管事实上只有一个匹配项。
Contains 的缺点
假设我有两个列表对象。
使用 Contains,它将搜索 List 2 中的每个 List 1 项目,这意味着迭代将发生 49 次!
I will go for Inner Join in this context. If I would have used contains, it would iterate 6 times despite if the fact that there are just one match.
Disadvantages of Contains
Suppose I have two list objects.
Using Contains, it will search for each List 1 item in List 2 that means iteration will happen 49 times !!!
这可能是您可以直接使用 LINQ 扩展方法来检查 in 子句的可能方式
This could be the possible way in which you can directly use LINQ extension methods to check the in clause
我还尝试使用类似 SQL-IN 的东西 - 针对实体数据模型进行查询。 我的方法是使用字符串生成器来组成一个大的 OR 表达式。 这太难看了,但恐怕这是目前唯一的出路。
现在,看起来像这样:
在此上下文中使用 GUID:正如您在上面所看到的,在查询字符串片段中的 GUID 本身之前始终有单词“GUID”。 如果不添加此内容,
ObjectQuery.Where
会引发以下异常:在 MSDN 论坛中找到了这一点,记住这一点可能会有所帮助。
I also tried to work with an SQL-IN-like thing - querying against an Entity Data Model. My approach is a string builder to compose a big OR-expression. That's terribly ugly, but I'm afraid it's the only way to go right now.
Now well, that looks like this:
Working with GUIDs in this context: As you can see above, there is always the word "GUID" before the GUID ifself in the query string fragments. If you don't add this,
ObjectQuery<T>.Where
throws the following exception:Found this in MSDN Forums, might be helpful to have in mind.
BenAlabaster 答案的替代方法
首先,您可以像这样重写查询:
当然,这更“冗长”并且写起来很痛苦,但它的工作原理都是一样的。
因此,如果我们有一些实用方法可以轻松创建此类 LINQ 表达式,我们就可以开展业务。
使用实用程序方法,您可以编写如下内容:
这将构建一个具有相同效果的表达式:
但更重要的是,它实际上适用于 .NET 3.5 SP1。
这是使这成为可能的管道函数:
我不会尝试解释此方法,只是说它本质上使用 valueSelector 为所有值构建谓词表达式(即 p => p.User_Rights)和将这些谓词组合在一起以创建完整谓词的表达式
来源:http://blogs.msdn.com/b/alexj/archive/2009/03/26/tip-8-writing-where -in-style-queries-using-linq-to-entities.aspx
An alternative method to BenAlabaster answer
First of all, you can rewrite the query like this:
Certainly this is more 'wordy' and a pain to write but it works all the same.
So if we had some utility method that made it easy to create these kind of LINQ expressions we'd be in business.
with a utility method in place you can write something like this:
This builds an expression that has the same effect as:
But which more importantly actually works against .NET 3.5 SP1.
Here is the plumbing function that makes this possible:
I'm not going to try to explain this method, other than to say it essentially builds a predicate expression for all the values using the valueSelector (i.e. p => p.User_Rights) and ORs those predicates together to create an expression for the complete predicate
Source: http://blogs.msdn.com/b/alexj/archive/2009/03/26/tip-8-writing-where-in-style-queries-using-linq-to-entities.aspx
真实例子:
Real example:
这不完全是 IN 运算符,但它可能会帮助您获得预期的结果,并且可能是一种更通用的方法(因为它允许比较两个集合): INTERSECT
这是一个工作示例,
我想应该对性能进行基准测试(针对当前接受的答案)以完全验证此解决方案...
编辑:
正如 Gert Arnold 要求的示例(EF 6):
这段代码为我提供了名字和/或姓氏与“John”或“Doe”匹配的任何用户:
This isn't exactly the IN operator, but it might help you get the expected result and maybe a more generic approach (as it allows two collections to be compared) : INTERSECT
here's a working example
I guess performance should be benchmarked (against the currently accepted answer) to fully validate this solution...
EDIT :
As Gert Arnold asked for an example (EF 6) :
This piece of code gives me any user whose first and/or last name matches "John" or "Doe" :
查询语法:
将从“populationdata”中选择月份位于字符串数组“month”中的记录。
Query syntax:
Will select records from "populationdata" where the month is "in" the array of strings "month".