I think the answer from Bent gives you very nice DSL for constructing the standard SqlCommand
objects. That might very well be just what you need - if you just want nicer syntax for creating a couple of commands, it will work perfectly.
If you wanted to do more things with your SQL commands, then the DSL has one limitation, which is that it is still based on the underlying mutable SqlCommand
type - it looks functional, but it mutates objects under the cover, which might get you in trouble.
A more comprehensive option would be to define your own functional types to capture the domain - that is, the kind of queries you want to run:
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 }
Then you can construct queries using normal F# types (and you could even implement a DSL like the one Bent suggested on top of this, while still keeping things immutable):
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 ] }
The last bit would be to write a function that takes command and a connection and turns it into 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
What is the best approach will depend on your use case - and interacting with databases is inherently impure, so perhaps keeping things isolated and impure is perfectly fine. Though I wanted to show this as a possible option if you wanted to be more functional and focus on the domain (using the strong domain-driven modelling side of F#!).