F#向SQL Server插入一个列表
我一直在试图找出从F#插入SQL Server的方法。F#向SQL Server插入一个列表
我有一个F#函数,可以在用户定义的模式之后遍历文件夹内的所有文件。然后我可以使用返回的数据放入列表或(理想情况下)插入到数据库中。
我已经有一个工作嵌入到-SQL函数可以正常工作:
let execNonQuery conn s =
let comm =
new SqlCeCommand(s, conn)
try
comm.ExecuteNonQuery() |> ignore
with e ->
printf "Error : %A\n" e
let string = "insert into MyTable (MyColumn) values ('test .. again')"
execNonQuery conn string; // works
我试图让这个方法才能正常工作:
let rec getAllFiles dir pattern =
seq { yield! Directory.EnumerateFiles(dir, pattern)
for d in Directory.EnumerateDirectories(dir) do
yield! getAllFiles d pattern }
let getApplications (dir : string) (extension : string) =
getAllFiles dir extension
//|> Seq.toList // If I need to create a list of returned values
|> Seq.iter (fun s -> SQLInsertString s) // This does not work as it complains about the function not being of type unit
如果我使用Seq.toList
只能按以下方式调用函数,它的工作原理:
getApplications "C:\Admin" "*.txt" // works
另一件我不明白的事情是,如何创建一个接受Value的字符串的工作插入命令。例如:
let SQLInsertString s = "insert into MyTable (MyColumn) values (%s)" //does not work
传递参数的最佳方式一个查询是使用SqlCeParameter
。这比编写字符串更容易(因为您不需要编码字符串和转义引号)并且它也更安全,因为您避免了SQL injection attack。这是一个基本的例子:
let sqlInsertString value =
// Create and open connection ('use' makes sure it gets closed at the end)
use conn = new SqlCeConnection("...");
conn.Open()
// Create a command with a parameter named '@str'
let cmd = new SqlCeCommand("INSERT INTO MyTable (MyColumn) values (@str)", conn)
// Create parameter '@str' with string value 'value' and add it to the command
let param = new SqlCeParameter("@str", SqlDbType.NVarChar, value)
cmd.Parameters.Add(param)
// Now run the command (exception handling omitted)
cmd.ExecuteNonQuery() |> ignore
使用此功能,您现在应该能够使用Seq.iter
。该功能需要一个string
插入并返回unit
(没有值),因此它可以被传递到Seq.iter
:
let getApplications (dir : string) (extension : string) =
getAllFiles dir extension
|> Seq.iter (fun s -> sqlInsertString s)
或者,你可以写的最后一行,就像|> Seq.iter sqlInsertString
。如果你这样做,你基本上是说,参数s
应该直接传递给sqlInsertString
函数。
你快到了。问题是sqlInsertString
返回string
这是不合法的使用Seq.iter
。
你在做什么与sqlInsertString
是使用字符串格式创建一个字符串。
let sqlInsertString s =
sprintf "insert into MyTable (MyColumn) values (%s)" s
现在你可以使用execNonQuery
上sqlInsertString
结果实际数据插入到数据库:它具有sprintf
功能非常适合。由于execNonQuery
回报unit
,它可以很容易地在Seq.iter
使用:
// Assuming conn is a global and already defined variable.
let getApplications (dir : string) (extension : string) =
getAllFiles dir extension
|> Seq.iter (fun s -> execNonQuery conn (sqlInsertString s))
由于类型的注释是多余的,你的代码可以在一个更地道的方式改写:
let getApplications dir extension conn =
getAllFiles dir extension
|> Seq.iter (sqlInsertString >> execNonQuery conn)
非常感谢。这个答案也像一个魅力。我不得不选择一个答案作为预期的答案,Tomas解释了如何使用参数。 – 2012-02-15 15:35:24
非常感谢Tomas,作品像一个魅力。现在我也看到了它更好 – 2012-02-15 15:35:45