此表达式应具有 IDataReader 类型,但此处具有 SqlDataReader 类型



下面的代码没有将我的返回值 SqlDataReadergetReader正确地强制转换为IDataReader调用 Seq.unfold我做错了什么?

open System.Data
open System.Data.SqlClient
open System.Configuration
type Foo = { id:int; name:string }
let populateFoo (r:IDataReader) =
    let o = r.GetOrdinal
    { id = o "id" |> r.GetInt32; name = o "name" |> r.GetString; }
let iter populateObject (r:IDataReader)  =
    match r.Read() with
    | true -> Some(populateObject r, r)
    | _    -> None
let iterFoo = iter populateFoo
let getReader : IDataReader =
    let cnstr = ConfigurationManager.ConnectionStrings.["db"].ConnectionString
    let cn = new SqlConnection(cnstr)
    let cmd = new SqlCommand("select * from Foo", cn)
    cmd.ExecuteReader()
let foos = Seq.unfold iterFoo getReader
F#

不会像 C# 那样自动向上转换,除非在某些特定情况下(请参阅规范,第 14.4.2 节)。

您必须显式强制转换表达式:cmd.ExecuteReader() :> IDataReader然后您可以在 getReader 之后删除类型注释。

或者,您可以让该函数在调用站点返回SqlDataReader和向上转换:

let foos = getReader :> IDataReader |> Seq.unfold iterFoo

如果unfold是具有如下签名的类型的静态成员:

type T() =
    static member unfold(a, b:IDataReader) = Seq.unfold a b

您可以直接执行T.unfold(iterFoo, getReader),它会自动向上转换。这是规范中提到的情况之一。

相关内容

  • 没有找到相关文章

最新更新