Mysql
 sql >> Base de données >  >> RDS >> Mysql

F# Beginner :récupérer un tableau de données d'un serveur

Le type Seq a une fonction intéressante pour gérer les curseurs de base de données appelée generate_using (voir Manuel F# et le chapitre sur l'accès aux données dans Foundations of F# ). Il s'agit d'une fonction d'ordre supérieur qui prend une fonction pour ouvrir le curseur et une autre (appelée à plusieurs reprises) pour traiter les enregistrements à partir du curseur. Voici du code qui utilise generate_using pour exécuter une requête sql :

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

Par exemple, pour répertorier toutes les tables d'une base de données Oracle, nous devons définir un type de définition de colonne et invoquer executeSqlReader comme suit :

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"