在F#中使用SqlDataReader
在C#中,我使用sql脚本将数据添加到List中,其中T将是一个具有映射到sql脚本的字段/属性的类。
我怎么能在F#中做到这一点? 这篇文章以标准方式使用存储过程。
using (conn) { conn.Open(); using (SqlCommand cmd = new SqlCommand("dbo.query_here", conn)) { cmd.CommandText = "dbo.query_here"; cmd.CommandType = System.Data.CommandType.StoredProcedure; cmd.CommandTimeout = 600; cmd.Parameters.Add(new SqlParameter("@x1", Convert.ToString(x))); cmd.Parameters.Add(new SqlParameter("@y1", y)); cmd.Parameters.Add(new SqlParameter("@z1", z)); SqlDataReader reader = cmd.ExecuteReader(); while (reader.Read()) { MyListOfClasses.Add(new MyDataClass(reader.GetInt32(reader.GetOrdinal("x")) reader.GetDouble(reader.GetOrdinal("y")), reader.GetDouble(reader.GetOrdinal("a")), reader.GetDouble(reader.GetOrdinal("b")))); } reader.Close(); } conn.Close();
我意识到F#并不像这样直截了当,但我需要以类似的方式将这些数据放入F#列表中。 也更喜欢那些本质上不起作用的建议,并遵循与C#代码类似的模式。
在之前的一个post中有人建议使用记录,但这与SqlDataReader无关。 最好有一个类列表,这样我就可以在每个项目上使用getter和setter。
我应该在不可避免的评论之前加上“为什么不只是使用C#”。 很明显我可以使用C#,但我正在探索在F#中编写算法的可能性,为此我需要从SQL Server获取原始数据。
如果您想在F#列表中返回results
,列表推导适合在此处使用。 使用use
关键字,您不需要显式处置对象。
use conn = (* Initialize sql connection here *) conn.Open() use cmd = new SqlCommand("dbo.query_here", conn) cmd.CommandText <- "dbo.query_here" cmd.CommandType <- System.Data.CommandType.StoredProcedure cmd.CommandTimeout <- 600 cmd.Parameters.Add(new SqlParameter("@x1", Convert.ToString(x))) cmd.Parameters.Add(new SqlParameter("@y1", y)) cmd.Parameters.Add(new SqlParameter("@z1", z)) use reader = cmd.ExecuteReader() let results = [ while reader.Read() do yield new MyDataClass(reader.GetInt32(reader.GetOrdinal("x")), reader.GetDouble(reader.GetOrdinal("y")), reader.GetDouble(reader.GetOrdinal("a")), reader.GetDouble(reader.GetOrdinal("b"))) ]
使用普通的旧ADO.NET处理数据库实际上可以使用F#动态运算符?
。 我写了一篇MSDN文章,它实现了一个帮助程序 ,可以让你编写类似于:
let myListOfClasses = [ let db = new DynamicDatabase(connectionString) let rows = db.Query?query_here(string x, y, z) for r in rows do yield MyDataClass(row?x, row?y, row?a, row?b) ]
这使用动态调用操作符?
调用存储过程( db.Query?query_here
)。 当你调用它时,你可以给它参数,好像它是一个普通的函数调用(它会将它们添加为SQL参数)。 然后你也可以使用row?x
来读取属性 – 这可以从MyDataClass
参数的类型中推断出类型,所以假设这些匹配,你不需要自己编写类型转换。
以下是MSDN教程的链接,讨论了这一点:
- 如何:动态调用存储过程
- 第1步:创建数据库并显示轮询选项
- 第2步:为选项实施投票
你可以读这个
链接: http : //www.codeproject.com/Articles/95656/Using-a-DataRader-like-a-List-in-F
let rdr = cmd.ExecuteReader() rdr |> SomeRecord.asSeq // project datareader into seq |> Seq.sumBy (fun r-> r.val1 * r.val2) // now you can use all the Seq operators // that everybody knows.
未经测试的F#翻译
use conn = ??? conn.Open() using new SqlCommand("dbo.query_here", conn)(fun cmd -> cmd.CommandText <- "dbo.query_here" cmd.CommandType <- System.Data.CommandType.StoredProcedure cmd.CommandTimeout <- 600 cmd.Parameters.Add(new SqlParameter("@x1", Convert.ToString(x))) cmd.Parameters.Add(new SqlParameter("@y1", y)) cmd.Parameters.Add(new SqlParameter("@z1", z)) let reader = cmd.ExecuteReader() while (reader.Read()) do MyListOfClasses.Add(new MyDataClass(reader.GetInt32(reader.GetOrdinal("x")) reader.GetDouble(reader.GetOrdinal("y")), reader.GetDouble(reader.GetOrdinal("a")), reader.GetDouble(reader.GetOrdinal("b")))) reader.Close() ) conn.Close() MyListOfClasses.ToArray() |> List.ofArray