6

如何执行类似于 SQL IN 查询的查询表达式?

我正在尝试按照以下方式做一些事情:

let customerNumbers = set ["12345"; "23456"; "3456"]
let customerQuery = query {
    for c in dataContext.Customers do
    where(customerNumbers.Contains(c.CustomerNumber))
    select c
}

但我收到一个错误:

System.NotSupportedException: Method 'Boolean Contains(System.String)' has no supported translation to SQL.

在http://msdn.microsoft.com/en-us/library/hh225374.aspx查看查询表达式的文档,我应该对包含部分使用另一个查询,但此代码不起作用,示例已损坏:

// 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
}

idQuery 实际上不包含任何“包含”方法。

我也试过:

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
}

但这给出了这个错误信息:

System.NotSupportedException: Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator

经过更多测试后,我注意到除了 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
}
4

1 回答 1

7

我认为问题来自 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
}

或者,等效地,您可以添加非 LINQ-to-SQL 查询

let idQuery = query { for id in customerNumbers do select id }

set枚举屈服没有问题,seq<string>然后将其Contains用作

....
where (idQuery.Contains(c.CustomerNumber))
....

或者,首先,您可以保留您的customerNumbersas seq

let customerNumbers = set ["12345"; "23456"; "3456"] |> Set.toSeq

并将其用作直觉提示:

....
where(customerNumbers.Contains(c.CustomerNumber))
....
于 2014-02-05T17:25:24.297 回答