Convert Sequence.Generate to Sequence Expression
I have the following code that uses Sequence objects to read data from a database table. V1 works correctly but since the Seq.generate function is deprecated I receive compiler warnings.
I tried to rerplace this code with V2 (below) but it does not work correctly - basically the reader is opened but only the first record is read - IOW - Read Next does not work correctly.
To avoid compilation errors/warnings I need to convert V1 code to use a sequence expression.
Any ideas on the correct approach here.
(BTW - This code is based on examples in Rob Pickering's Beginning F# book - (Data Access/ADO.NET Section).
********************** 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
yiel开发者_开发百科d 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
You need to move around a few control structures to get this working.
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
The only thing you left out is: while reader.Read() do
let generateSequence connName cmdString =
seq {
use reader = openReader connName cmdString
while reader.Read() do
yield readRow reader
}
精彩评论