Parameters F#使用参数设置SQLCommand的最佳方法
我的F#程序需要与SQL Server对话。在一部分中,我有如下内容:Parameters F#使用参数设置SQLCommand的最佳方法,parameters,f#,sqlcommand,Parameters,F#,Sqlcommand,我的F#程序需要与SQL Server对话。在一部分中,我有如下内容: let workFlowDetailRuncommand = new SqlCommand(query, econnection) workFlowDetailRuncommand.CommandTimeout <- 100000 workFlowDetailRuncommand.Parameters.Add("@1", SqlDbType.Int).Value <- 42 workF
let workFlowDetailRuncommand = new SqlCommand(query, econnection)
workFlowDetailRuncommand.CommandTimeout <- 100000
workFlowDetailRuncommand.Parameters.Add("@1", SqlDbType.Int).Value <- 42
workFlowDetailRuncommand.Parameters.Add("@2", SqlDbType.VarChar).Value <- "answer"
workFlowDetailRuncommand.Parameters.Add("@3", SqlDbType.VarChar).Value <- mydate.ToString("yyyy.MM.dd")
workFlowDetailRuncommand.Parameters.Add("@4", SqlDbType.VarChar).Value <- "D. Adams"
workFlowDetailRuncommand.Parameters.Add("@5", SqlDbType.DateTime).Value <- DateTime.Now
workFlowDetailRuncommand.Parameters.Add("@6", SqlDbType.Text).Value <- filename
让workFlowDetailRuncommand=新建SqlCommand(查询、econnection)
workFlowDetailRuncommand.CommandTimeout我还没有测试过这个
创建一些辅助函数
let createSqlCommand query connection =
new SqlCommand(query, connection)
let setTimeout timeout (sqlCommand: SqlCommand) =
sqlCommand.CommandTimeout <- timeout
sqlCommand
let addInt name (value: int) (sqlCommand: SqlCommand) =
sqlCommand.Parameters.Add(name, SqlDbType.Int).Value <- value
sqlCommand
如果您有一个int,那么始终使用SqlDbType.int是有意义的
但是,如果您有一个字符串,那么字段类型有几个明显的候选者。因此,最好让addXxx函数的名称反映字段类型,而不是F#/.NET类型。这样您就可以创建addVarChar、addNVarChar、addChar等
|> addInt "@i1" myInt
|> addDateTime "@dt1" myDateTime
|> addText "@tagText" myTagText
|> addNVarChar "@letter" myLetterBody
我认为Bent的答案为您提供了非常好的DSL,用于构建标准的SqlCommand
对象。这很可能正是您所需要的——如果您只是想要更好的语法来创建两个命令,那么它将完美地工作
如果您想用SQL命令做更多的事情,那么DSL有一个限制,那就是它仍然基于底层的可变SqlCommand
类型-它看起来很实用,但它会在封面下改变对象,这可能会给您带来麻烦
一个更全面的选项是定义您自己的功能类型以捕获域,即您想要运行的查询类型:
type Parameter =
| Int of int
| VarChar of string
| Text of string
| DateTime of System.DateTime
type Command =
{ Query : string
Timeout : int
Parameters : (string * Parameter) list }
然后,您可以使用普通的F#类型构造查询(您甚至可以实现类似Bent在此基础上建议的DSL,同时仍然保持不变):
最后一点是编写一个函数,该函数接受命令和连接,并将其转换为SqlCommand
:
let createSqlCommand cmd connection =
let sql = new SqlCommand(cmd.Query, connection)
sql.CommandTimeout <- cmd.Timeout
for name, par in cmd.Parameters do
let sqlTyp, value =
match par with
| Int n -> SqlDbType.Int, box n
| VarChar s -> SqlDbType.VarChar, box s
| Text s -> SqlDbType.Text, box s
| DateTime dt -> SqlDbType.DateTime, box dt
sql.Parameters.Add(name, sqlTyp).Value <- value
sql
让createSqlCommand cmd连接=
让sql=newsqlcommand(cmd.Query,connection)
sql.CommandTimeout SqlDbType.Int,框n
|VarChar s->SqlDbType.VarChar,框s
|Text s->SqlDbType.Text,框s
|DateTime dt->SqlDbType.DateTime,框dt
Add(name,sqlTyp).Value在这里查看SqlCommandProvider。可能不完全适合您的用例(特别是在查询是动态的情况下),但可以很好地处理参数:我使用这种技术处理基于F#类型的大量XML的构造,它工作得非常好。这太棒了!我开始用它了。一个后续问题。由于SQLConnection支持Dispose,我一直在做use connection=new SQLConnection(connString)
如何将其融入这个想法?@user1443098这就是为什么我没有在命令中包含SQLConnection
类型的原因-这样,您可以单独配置命令,然后使用use
打开连接,调用createSqlCommand
并运行SQL命令,然后关闭连接。仍然有必要的部分,但它被推到了最后。
let cmd =
{ Query = query
Timeout = 100000
Parameters =
[ "@1", Int 42
"@2", VarChar "answer"
"@3", VarChar (mydate.ToString("yyyy.MM.dd"))
"@4", VarChar "D. Adams"
"@5", DateTime DateTime.Now
"@6", Text filename ] }
let createSqlCommand cmd connection =
let sql = new SqlCommand(cmd.Query, connection)
sql.CommandTimeout <- cmd.Timeout
for name, par in cmd.Parameters do
let sqlTyp, value =
match par with
| Int n -> SqlDbType.Int, box n
| VarChar s -> SqlDbType.VarChar, box s
| Text s -> SqlDbType.Text, box s
| DateTime dt -> SqlDbType.DateTime, box dt
sql.Parameters.Add(name, sqlTyp).Value <- value
sql