在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