使常量从F#中的函数生成的字符串

问题描述 投票:1回答:1

我是F#的新手,我一直在从这个问题中拔头发:

SqlCommandProvider需要一个常量字符串,下面的函数无法提供该常量字符串。在F#交互式中运行它会返回“这不是有效的常量表达式或自定义属性值。”

let textgen (RIC: string, price: float, volume: int, inst: int, time:string) =
    let mutable mystring = "INSERT INTO hsbc(RIC, price, volume, type, time) VALUES (st1, st2, st3, st4, st5)"
    mystring <- mystring.Replace ("st1", RIC)
    mystring <- mystring.Replace ("st2", price.ToString())
    mystring <- mystring.Replace ("st3", volume.ToString())
    mystring <- mystring.Replace ("st4", inst.ToString())
    mystring <- mystring.Replace ("st5", time)
    mystring


let sqlcommand1 = textgen("0005.hk",71.2,5000,1,"2019-07-18 10:34:09.193")

type writedata4=SqlCommandProvider<sqlcommand1,connStr>
do
    let cmd6 = new writedata4(connStr)
    cmd6.Execute()
    0

我已经进行了一些研究,并且知道这是sqlcommand1在编译期间不是常量的问题。所以我尝试了这个:

[<Literal>]
let sqlcommand1 = textgen("0005.hk",71.2,5000,1,"2019-07-18 10:34:09.193")

再次返回:“这不是有效的常量表达式或自定义属性值”

任何帮助将不胜感激,非常感谢!

更新:谢谢!我改编了@Mark Pattison的代码,此方法有效:

let mywrite(RIC: string, price: float, volume: int, inst: int, time:string) =
    use cmd99 = new SqlCommandProvider<"INSERT INTO hsbc(RIC, price, volume, type, time) VALUES (@st1, @st2, @st3, @st4, @st5)", connStr>(connStr)
    cmd99.Execute(st1=RIC,st2=price,st3=volume,st4=inst,st5=System.DateTime.Parse time)
    |> ignore

但是,官方文档确实提到:

let cmd = new SqlCommandProvider<const(SqlFile<"GetDate.sql">.Text), connStr>(connStr)
cmd.Execute() |> ignore

由于该命令是从外部文本加载的,因此编译时的确定性甚至应该更低,并且不起作用(但它似乎起作用)。你能告诉我为什么吗?谢谢

f#
1个回答
4
投票

想法是命令文本是编译时常量。显然,sqlcommand1不能,因为它是在运行时通过调用textgen创建的。

这是一个如何从@使用docs创建参数化命令的示例:

open FSharp.Data

[<Literal>]
let connectionString = 
    @"Data Source=.;Initial Catalog=AdventureWorks2012;Integrated Security=True"

do
    use cmd = new SqlCommandProvider<"
        SELECT TOP(@topN) FirstName, LastName, SalesYTD 
        FROM Sales.vSalesPerson
        WHERE CountryRegionName = @regionName AND SalesYTD > @salesMoreThan 
        ORDER BY SalesYTD
        " , connectionString>(connectionString)

    cmd.Execute(topN = 3L, regionName = "United States", salesMoreThan = 1000000M) |> printfn "%A"

//output
//seq
//    [("Pamela", "Ansman-Wolfe", 1352577.1325M);
//     ("David", "Campbell", 1573012.9383M);
//     ("Tete", "Mensa-Annan", 1576562.1966M)]

您可以看到命令字符串本身(从SELECT...开始)是一个常量字符串。


0
投票

这里的问题

[<Literal>]
let sqlcommand1 = textgen("0005.hk",71.2,5000,1,"2019-07-18 10:34:09.193")

是您要尝试将文字属性应用于不是字符串的内容

[<Literal>]
let sqlcommand1 = "0005.hk",71.2,5000,1,"2019-07-18 10:34:09.193"

可能是您的实际意图。但是,您在此处采用代码构建SQL插入的整个方法充满了问题。即使可以使用,您也可以打开SQL注入问题,而Mark Pattison展示的方法更安全。

© www.soinside.com 2019 - 2024. All rights reserved.