返回值和if表达式

时间:2013-11-27 17:27:57

标签: ado.net f#

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

  

警告FS0020:此表达式应为“unit”类型,但类型为“login option”。使用'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): error FS0001: Type mismatch. Expecting a
    'a -> login option    
but given a
    'a -> unit    
The type 'login option' does not match the type 'unit'
> 

1 个答案:

答案 0 :(得分:2)

问题是您的if表达式后跟另一行:

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

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

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

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

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