Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linq SqlDataProvider-动态编写where子句并执行命令_Linq_F# - Fatal编程技术网

Linq SqlDataProvider-动态编写where子句并执行命令

Linq SqlDataProvider-动态编写where子句并执行命令,linq,f#,Linq,F#,我有以下要求: 使用动态生成的where子句查询SQL表,该子句应在运行时由列表组成 [<Literal>] let connectionString = "Data Source=..." type sql = SqlDataProvider< ConnectionString = connectionString, DatabaseVendor = Common.DatabaseProviderTy

我有以下要求:

使用动态生成的where子句查询SQL表,该子句应在运行时由列表组成

[<Literal>]
let connectionString = "Data Source=..."

type sql = SqlDataProvider< 
                  ConnectionString = connectionString,
                  DatabaseVendor = Common.DatabaseProviderTypes.MSSQLSERVER,
                  UseOptionTypes = true>
let ctx = sql.GetDataContext()

type Key = {k:string;v:string}

let findCustomersByKeys (keys:Key list) =
    query{
         for c in ctx.Dbo.Customers do
         where (keys.Any(fun k -> c.k = k.k && c.v = k.v))//this is what i wish i could do
         select c
    }

[]
让connectionString=“数据源=…”
类型sql=SqlDataProvider<
ConnectionString=ConnectionString,
DatabaseVendor=Common.DatabaseProviderTypes.MSSQLSERVER,
UseOptionTypes=true>
设ctx=sql.GetDataContext()
类型Key={k:string;v:string}
让我们查找客户密钥(密钥:密钥列表)=
质疑{
对于ctx.Dbo.Customers中的c
where(key.Any(fun k->c.k=k.k&&c.v=k.v))//这就是我希望能做的
选择c
}
有没有办法用SqlDataProvider在F#中实现这一点? 还有其他技术吗?

您可以使用它动态构造谓词,并将其直接拼接到查询表达式中,因为查询表达式实际上是编译成引号的

谓词是通过折叠键、递归地将or条件拼接到初始条件
false
上而构建的。但是,因为我们不能在这里结束
c
,所以我们还需要将每个条件包装在一个函数中,并通过谓词链执行参数

open Microsoft.FSharp.Quotations

type Key = {k:string;v:string}

let findCustomersByKeys (keys:Key list) =
    let predicate = 
        keys
            |> List.fold
                (fun (acc: Expr<Key -> bool>) k ->
                    <@ fun c -> (%acc) c || c.k = k.k && c.v = k.v @>)
                <@ fun c -> false @>

    query {
         for c in ctx.Dbo.Customers do
         where ((%predicate) c)
         select c
    }
打开Microsoft.FSharp.quotes
类型Key={k:string;v:string}
让我们查找客户密钥(密钥:密钥列表)=
let谓词=
钥匙
|>List.fold
(乐趣(acc:Expr bool>)k->
(%acc)c|c.k=k.k&&c.v=k.v@>)
假@>
质疑{
对于ctx.Dbo.Customers中的c
其中((%谓词)c)
选择c
}
您可以使用动态构造谓词,并将其直接拼接到查询表达式中,因为查询表达式实际上是编译成引号的

谓词是通过折叠键、递归地将or条件拼接到初始条件
false
上而构建的。但是,因为我们不能在这里结束
c
,所以我们还需要将每个条件包装在一个函数中,并通过谓词链执行参数

open Microsoft.FSharp.Quotations

type Key = {k:string;v:string}

let findCustomersByKeys (keys:Key list) =
    let predicate = 
        keys
            |> List.fold
                (fun (acc: Expr<Key -> bool>) k ->
                    <@ fun c -> (%acc) c || c.k = k.k && c.v = k.v @>)
                <@ fun c -> false @>

    query {
         for c in ctx.Dbo.Customers do
         where ((%predicate) c)
         select c
    }
打开Microsoft.FSharp.quotes
类型Key={k:string;v:string}
让我们查找客户密钥(密钥:密钥列表)=
let谓词=
钥匙
|>List.fold
(乐趣(acc:Expr bool>)k->
(%acc)c|c.k=k.k&&c.v=k.v@>)
假@>
质疑{
对于ctx.Dbo.Customers中的c
其中((%谓词)c)
选择c
}

我的意思是,只有在运行时才能知道列表的大小,并且可以编译where子句。当您听到动态生成时,开始使用ORM,比如Dapper。另一种方法是按照答案中的建议,使用引号生成查询,但面对现实,每个人都会因此而恨你。我也做过一次:当然你也可以使用dynamic/expandoobject。我的意思是,只有在运行时才能知道列表的大小,并且可以编译where子句。当你听到动态生成时,开始使用ORM,比如Dapper。另一种方法是按照答案中的建议,使用引号生成查询,但面对现实,每个人都会因此而恨你。我也做过一次:当然你也可以使用dynamic/expandoobject。更新了答案。这比我想象的要复杂,有很多边缘案例,但我认为结果相当可读。更新了答案。这比我想象的要复杂,有很多边缘案例,但我认为结果相当可读。