【问题标题】:Return value and if expression返回值和 if 表达式
【发布时间】:2013-12-13 11:43:27
【问题描述】:

我有以下代码从 SQL 数据库中获取一行。它返回记录或无。但是,它没有返回,因为 getLogin 的类型为 unit = () 并且有警告

警告 FS0020:此表达式应具有“单元”类型,但具有“登录选项”类型。使用 'ignore' 丢弃表达式的结果,或使用 'let' 将结果绑定到名称。

如何解决问题?它是处理 Ado.Net 的最佳方式吗?

type login = { userName: string; password: string; downloadDir: string}

let getLogin =
    let conn = new SqlConnection("Data Source=......;Integrated Security=SSPI;")

    try
        conn.Open()

        let cmd = new SqlCommand("select * FROM Login where website = 'xxx'", conn)
        cmd.CommandType <- CommandType.Text
        use reader = cmd.ExecuteReader() 
        if (reader.HasRows) then (
            reader.Read() |> ignore
            let userName = reader.GetString(5)
            let password = reader.GetString(6)
            printfn "%s" userName
            Some { userName = userName; password = password; downloadDir = "zzz" }
        )
        else (
            printfn "Cannot find login information."
            None
        )

        conn.Close()
    with
        | :? System.Data.SqlClient.SqlException as sqlEx -> printfn "%A" sqlEx.Message
        | _ -> printfn "Unknown Exception"

更新: 我已根据 Thomas 的建议更新了代码。

let getLogin =
    use conn = new SqlConnection("Data Source=mdyptcafgprd101;Initial Catalog=App;Integrated Security=SSPI;")

    try
        conn.Open()

        let cmd = new SqlCommand("select * FROM app.WebCrawler.LoginLbl where website = 'CTSLink'", conn)
        cmd.CommandType <- CommandType.Text
        use reader = cmd.ExecuteReader() 
        if (reader.HasRows) then (
            reader.Read() |> ignore
            let userName = reader.GetString(5)
            let password = reader.GetString(6)
            Some { userName = userName; password = password; downloadDir = "zzz" }
        )
        else (
            printfn "Cannot find login information."
            None
        )

    with
        | :? System.Data.SqlClient.SqlException as sqlEx -> printfn "%A" sqlEx.Message
        | _ -> printfn "Unknown Exception"

但是,现在它在| :? System... 行出现以下错误。

s.fs(31,69):错误 FS0001:类型不匹配。期待一个 'a -> 登录选项 但给定一个 'a -> 单位 “登录选项”类型与“单位”类型不匹配 >

【问题讨论】:

    标签: ado.net f#


    【解决方案1】:

    问题是你的if 表达式后面跟着另一行:

    if reader.HasRows then
      (...)
    else
      (...)
    conn.Close()
    

    ...因此编译器认为您忽略了if 的结果,而是返回最后一个表达式的结果,即conn.Close()

    解决此问题的最简单方法是使用 use 构造 - 它会在超出范围时自动处理 conn 值,因此您不需要最后一行,只需使用 if作为代码中的最后一个表达式:

    use conn = (...)
    if reader.HasRows then
      (...)
    else
      (...)
    

    此外,您需要在 with ... 分支中返回一些结果 - 处理异常,您需要引发另一个异常或返回有效值 - 在这种情况下,可能是 None

    【讨论】:

    • 谢谢。我将代码更改为使用use conn。但是,它在异常处理程序行上有error FS0001: Type mismatch. Expecting a 'a -&gt; login option but given a 'a -&gt; unit The type 'login option' does not match the type 'unit'的错误。
    • @dc7a9163d9 - 您需要使异常处理程序中的条目具有与 if 相同的返回类型或重新抛出它们自己的异常。 (一个很好的例子是在printfn 之后添加None
    猜你喜欢
    • 2014-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-29
    相关资源
    最近更新 更多