Neo*_*que 6 f# query-expressions
如何执行类似于SQL IN查询的查询表达式?
我试图沿着这些方向做点什么:
let customerNumbers = set ["12345"; "23456"; "3456"]
let customerQuery = query {
for c in dataContext.Customers do
where(customerNumbers.Contains(c.CustomerNumber))
select c
}
Run Code Online (Sandbox Code Playgroud)
但我收到一个错误:
System.NotSupportedException: Method 'Boolean Contains(System.String)' has no supported translation to SQL.
Run Code Online (Sandbox Code Playgroud)
在http://msdn.microsoft.com/en-us/library/hh225374.aspx上查看查询表达式的文档我应该对contains部分使用另一个查询,但是这段代码不起作用,示例被破坏了:
// Select students where studentID is one of a given list.
let idQuery = query { for id in [1; 2; 5; 10] do select id }
query {
for student in db.Student do
where (idQuery.Contains(student.StudentID))
select student
}
Run Code Online (Sandbox Code Playgroud)
idQuery确实不包含任何"Contains"方法.
我也尝试过:
let customerNumbers = set ["12345"; "23456"; "3456"]
let customerQuery = query {
for c in dataContext.Customers do
where (query { for x in customerNumbers do exists (c.CustomerNumber=x)})
select r
}
Run Code Online (Sandbox Code Playgroud)
但是这会给出以下错误消息:
System.NotSupportedException: Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator
Run Code Online (Sandbox Code Playgroud)
经过一些测试,我注意到除了Gene的建议之外,以下内容也可以正常工作:
let customerNumbers = set ["12345"; "23456"; "3456"]
query {
for customer in dataContext.Customer do
where (query { for x in customerNumbers do contains customer.CustomerNumber})
select customer
}
Run Code Online (Sandbox Code Playgroud)
我认为问题来自F#Set实现方法的方式Contains.它属于ICollection接口,这个事实以某种方式扰乱了LINQ-to-SQL查询构建器.
如果你明确强制你Contains进入IEnumerable领土的扩展方法,一切都会好起来的:
let customerNumbers = set ["12345"; "23456"; "3456"]
let customerQuery = query {
for c in dataContext.Customers do
where((customerNumbers :> IEnumerable<string>).Contains(c.CustomerNumber))
select c
}
Run Code Online (Sandbox Code Playgroud)
或者,等效地,您可以添加非LINQ-to-SQL查询
let idQuery = query { for id in customerNumbers do select id }
Run Code Online (Sandbox Code Playgroud)
枚举set屈服没有问题,seq<string>然后用它Contains作为
....
where (idQuery.Contains(c.CustomerNumber))
....
Run Code Online (Sandbox Code Playgroud)
或者,首先,你可以保持你customerNumbers的seq:
let customerNumbers = set ["12345"; "23456"; "3456"] |> Set.toSeq
Run Code Online (Sandbox Code Playgroud)
并将其用作直觉提示:
....
where(customerNumbers.Contains(c.CustomerNumber))
....
Run Code Online (Sandbox Code Playgroud)