Bud*_*Joe 20 .net ado.net f# functional-programming
我刚开始学习F#.我昨晚写了这个F#/ ADO.NET代码.你会以什么方式改进语法 - 让它感觉像是惯用的F#?
let cn = new OleDbConnection(cnstr)
let sql = "SELECT * FROM People"
let da = new OleDbDataAdapter(new OleDbCommand(sql, cn))
let ds = new DataSet()
cn.Open()
let i = da.Fill(ds)
let rowCol = ds.Tables.[0].Rows
let rowCount = rowCol.Count
printfn "%A" rowCount
for i in 0 .. (rowCount - 1) do
let row:DataRow = rowCol.[i]
printfn "%A" row.["LastName"]
Run Code Online (Sandbox Code Playgroud)
注意:我确实发现语法检查器不喜欢rowCol.[i].["LastName"]处理双索引器的正确方法是什么?我不得不将代码分成两行.
另外,如果我没有沿着DataSet路由走下去并使用将其数据加载到F#记录中的SqlDataReader.我应该使用什么样的集合结构来包含记录?标准的.NET List <>?
Tom*_*cek 32
代码的关键部分是处理不起作用的.NET API,因此无法使代码的这一部分更具惯用性或更好.但是,函数式编程中的关键是抽象,因此您可以将这个(丑陋)代码隐藏到一些惯用和可重用的函数中.
为了表示F#中的数据集合,您可以使用标准F#列表类型(适用于功能数据处理)或seq<'a>(IEnumerable<'a>在封面下使用标准.NET ),这在使用其他.NET库时非常有效.
根据您在代码中的其他位置访问数据库的方式,以下可能有效:
// Runs the specified query 'sql' and formats rows using function 'f'
let query sql f =
// Return a sequence of values formatted using function 'f'
seq { use cn = new OleDbConnection(cnstr) // will be disposed
let da = new OleDbDataAdapter(new OleDbCommand(sql, cn))
let ds = new DataSet()
cn.Open()
let i = da.Fill(ds)
// Iterate over rows and format each row
let rowCol = ds.Tables.[0].Rows
for i in 0 .. (rowCount - 1) do
yield f (rowCol.[i]) }
Run Code Online (Sandbox Code Playgroud)
现在您可以使用该query函数来编写原始代码,大致如下:
let names = query "SELECT * FROM People" (fun row -> row.["LastName"])
printfn "count = %d" (Seq.count names)
for name in names do printfn "%A" name
// Using 'Seq.iter' makes the code maybe nicer
// (but that's a personal preference):
names |> Seq.iter (printfn "%A")
Run Code Online (Sandbox Code Playgroud)
你可以写的另一个例子是:
// Using records to store the data
type Person { LastName : string; FirstName : string }
let ppl = query "SELECT * FROM People" (fun row ->
{ FirstName = row.["FirstName"]; LastName = row.["LastName"]; })
let johns = ppl |> Seq.filter (fun p -> p.FirstName = "John")
Run Code Online (Sandbox Code Playgroud)
顺便说一句:关于Mau的建议,如果有更直接的方法使用语言结构编写代码,我就不会过度使用高阶函数for.iter上面的例子很简单,有些人会发现它更具可读性,但没有一般规则......
我在ADO.NET上为F#编写了一个函数包装器.使用此库,您的示例如下所示:
let openConn() =
let cn = new OleDbConnection(cnstr)
cn.Open()
cn :> IDbConnection
let query sql = Sql.execReader (Sql.withNewConnection openConn) sql
let people = query "select * from people" |> List.ofDataReader
printfn "%d" people.Length
people |> Seq.iter (fun r -> printfn "%s" (r?LastName).Value)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4513 次 |
| 最近记录: |