Seq प्रकार में Generate_using नामक डेटाबेस कर्सर को संभालने के लिए एक साफ-सुथरा कार्य है (देखें F# मैनुअल और डेटा एक्सेस अध्याय Founds of F# में ) यह एक उच्च क्रम का फ़ंक्शन है जो कर्सर को खोलने के लिए एक फ़ंक्शन लेता है और दूसरा (बार-बार कहा जाता है) कर्सर से रिकॉर्ड को संसाधित करने के लिए। यहां कुछ कोड दिया गया है जो एक sql क्वेरी को निष्पादित करने के लिए Generate_using का उपयोग करता है:
let openConnection (connectionName : string) =
let connectionSetting = ConfigurationManager.ConnectionStrings.Item(connectionName)
let connectionString = connectionSetting.ConnectionString
let connection = new OracleConnection(connectionString)
connection.Open()
connection
let generator<'a> (reader : IDataReader) =
if reader.Read() then
let t = typeof<'a>
let props = t.GetProperties()
let types = props
|> Seq.map (fun x -> x.PropertyType)
|> Seq.to_array
let cstr = t.GetConstructor(types)
let values = Array.create reader.FieldCount (new obj())
reader.GetValues(values) |> ignore
let values = values
|> Array.map (fun x -> match x with | :? DBNull -> null | _ -> x)
Some (cstr.Invoke(values) :?> 'a)
else
None
let executeSqlReader<'a> (connectionName : string) (sql : string) : 'a list =
let connection = openConnection connectionName
let opener() =
let command = connection.CreateCommand(CommandText = sql, CommandType = CommandType.Text)
command.ExecuteReader()
let result = Seq.to_list(Seq.generate_using opener generator)
connection.Close()
connection.Dispose()
result
उदाहरण के लिए Oracle डेटाबेस में सभी तालिकाओं को सूचीबद्ध करने के लिए हमें एक कॉलम परिभाषा प्रकार को परिभाषित करने और executeSqlReader को निम्नानुसार लागू करने की आवश्यकता है:
type ColumnDefinition = {
TableName : string;
ColumnName : string;
DataType : string;
DataLength : decimal;
}
let tableList = executeSqlReader<ColumnDefinition>
"MyDatabase"
"SELECT t.table_name, column_name, data_type, data_length FROM USER_TABLES t, USER_TAB_COLUMNS c where t.TABLE_NAME = c.table_name order by t.table_name, c.COLUMN_NAME"