将Sequence.Generate转换为序列表达式

时间:2011-04-09 02:42:49

标签: f# database-connection sequence sqldatareader

我有以下代码使用Sequence对象从数据库表中读取数据。 V1正常工作,但由于不推荐使用Seq.generate函数,我收到编译器警告。

我尝试用V2(下面)重新放置此代码,但它无法正常工作 - 基本上读者是打开但只读取第一条记录 - IOW - Read Next不会 工作正常。

为避免编译错误/警告,我需要转换V1代码以使用序列表达式。

这里有关于正确方法的任何想法。

(顺便说一句 - 此代码基于Rob Pickering的Beginning F#书中的示例 - (数据访问/ ADO.NET部分)。

********************** V1 - Sequence Approach - Deprecated ************************

// execute a command using the Seq.generate
let execCommand (connName: string) (cmdString: string) = 
    Seq.generate       
        // This function gets called to open a connection and create a reader
        (fun () -> openReader connName cmdString)
        // This function gets called to read a single item in
        // the enumerable for a reader/connection pair
        (fun reader -> readRow(reader))
        (fun reader -> reader.Dispose())

*********************** V2  Alternative - (Does not work) ***************************

let generateSequence connName cmdString =
       seq { // This function gets called to open a connection and
              //create a reader
              use reader = openReader connName cmdString
              // This function gets called to read a single item in
               // the enumerable for a reader/connection pair
              yield readRow(reader) }

// execute a command using the Seq.generate
let execCommand (connName: string) (cmdString: string) = 

    generateSequence connName cmdString


*****************************  Common Functions  **********************************

// Open a db connection
let openReader connName cmdString =
    let conn = openSQLConnection(connName)
    let cmd = conn.CreateCommand(CommandText=cmdString,
                                 CommandType = CommandType.Text)
    let reader = cmd.ExecuteReader(CommandBehavior.CloseConnection)

// read a row from the data reader
let readRow (reader: #DbDataReader) =
    if reader.Read() then
        let dict = new Dictionary<string, obj>()
        for x in [ 0 .. (reader.FieldCount - 1) ] do
            dict.Add(reader.GetName(x), reader.[x])
        Some(dict)
    else
        None

2 个答案:

答案 0 :(得分:1)

你唯一遗漏的是:while reader.Read() do

let generateSequence connName cmdString =
    seq { 
        use reader = openReader connName cmdString
        while reader.Read() do
            yield readRow reader 
    }

答案 1 :(得分:1)

您需要移动一些控制结构才能使其正常工作。

let generateSequence connName cmdString =
    seq { 
        use reader = openReader connName cmdString
        while reader.Read () do
            yield readRow reader
        yield None
    }

let readRow (reader:#DbDataReader) =
    let dict = new Dictionary<string, obj>()
    for x in [0..(reader.FieldCount - 1)] do
        dict.Add (reader.GetName(x), reader.[x])
    Some dict