我希望将此代码转换为使用F#list而不是C#list实现。
我正在连接数据库并且通常使用C#运行查询会创建一个类型列表,并在datareader具有值时继续添加列表。我如何将其转换为使用F#列表
let queryDatabase (connection: NpgsqlConnection) (queryString: string) =
let transactions = new List<string>()
let command = new NpgsqlCommand(queryString, connection)
let dataReader = command.ExecuteReader()
while dataReader.Read() do
let json = dataReader.GetString(1)
transactions.Add(json)
transactions
答案 0 :(得分:4)
这里的棘手问题是输入数据源本质上是必需的(你必须调用Read
来改变内部状态)。所以,你正在从命令性到功能性世界 - 所以你无法避免所有的变异。
我可能会使用list comprehension编写代码,它保留了类似的熟悉结构,但删除了显式变异:
let queryDatabase (connection: NpgsqlConnection) (queryString: string) =
[ let command = new NpgsqlCommand(queryString, connection)
let dataReader = command.ExecuteReader()
while dataReader.Read() do
yield dataReader.GetString(1) ]
答案 1 :(得分:1)
Tomas的回答是在产品代码中使用的解决方案。但为了学习F#和函数式编程,我使用tail recursion和cons运算符提供了我的代码段:
let drToList (dr:DataReader) =
let rec toList acc =
if not dr.Read then acc
else toList <| dr.GetString(1) :: acc
toList []
这个 tail 递归函数被编译成类似命令式的代码,因此没有堆栈溢出和快速执行。
另外,我建议您查看this C#thread和this F#文档,了解如何正确处理命令。基本上,你需要像这样使用smth:
let queryDb (conn: NpgsqlConnection) (qStr: string) =
use cmd = new NpgsqlCommand(qStr, conn)
cmd.ExecuteReader() |> drToList
如果我们更深入,你也应该考虑异常处理。