F# Новичок: получение массива данных с сервера

Я пытаюсь получить данные из базы данных MySQL.

Подход 2 - применить / стиль карты

Я использую Справочник MySQL ADO, чтобы попытаться построить эту систему. В частности, пример из 21.2.3.1.7.

(с использованием псевдокода)

let table = build_sequence(query.read)

Где query.read возвращает строку в таблице (или, скорее, список элементов, которые оказались строкой в ​​таблице). А переменная таблицы - это список списков, которые будут представлять таблицу, возвращаемую из запроса.

Я смотрел на приведенный ниже код, и, боюсь, его синтаксис не подходит.

Подход 1 - петлевой.

Проблема 1: это неэлегантно, требует изменяемого.

Проблема 2: Это просто чувствует неверно, исходя из моего предыдущего опыта работы с Prolog и Lisp. Должен быть более ... функциональный способ сделать это.

Я не уверен, с чего начать. Комментарии и мысли?

let reader : MySql.Data.MySqlClient.MySqlDataReader = command.ExecuteReader()

let arr = []

let mutable rowIter = 0
let readingLoop() =
    while(reader.Read()) do
        rowIter = rowIter + 1
        for i = 0 to reader.FieldCount do

            //set arr[someiterator, i] = reader.GetValue[i].ToString())
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
6
0
4 280
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Работать с императивными API без императивного выполнения может быть сложно. У меня нет MySql под рукой, но я сделал приближение, надеюсь, это послужит источником вдохновения. Seq.unfold - это функция, которую люди находят довольно классной, когда пробуют ее. List.init (или Array.init) также удобен для инициализации структур данных известного размера без использования изменяемых файлов.

#light

type ThingLikeSqlReader() =
    let mutable rowNum = 0
    member this.Read() =
        if rowNum > 3 then
            false
        else
            rowNum <- rowNum + 1
            true
    member this.FieldCount = 5
    member this.GetValue(i) = i + 1

let reader = new ThingLikeSqlReader()    
let data = reader |> Seq.unfold (fun (reader : ThingLikeSqlReader) ->
    if reader.Read() then
        Some (List.init reader.FieldCount (fun i -> reader.GetValue(i)), reader)
    else
        None) |> Seq.to_list 
printfn "%A" data
Ответ принят как подходящий

Тип Seq имеет удобную функцию для обработки курсоров базы данных, которая называется generate_using (см. F# Руководство и главу о доступе к данным в Основы F#). Это функция более высокого порядка, которая принимает одну функцию для открытия курсора и другую (вызываемую повторно) для обработки записей из курсора. Вот код, который использует generate_using для выполнения 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

Например, чтобы вывести список всех таблиц в базе данных 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"

В ПОРЯДКЕ. Я до сих пор не совсем доволен всеми синтаксическими элементами в этом, но я следую семантике, и она отвечает на мой вопрос. Большое Вам спасибо.

Paul Nathan 17.11.2008 19:32

Я бы использовал ключевое слово использовать для удаления соединения вместо того, чтобы делать это вручную.

Mauricio Scheffer 14.01.2009 07:24

По прошествии времени я все еще не могу разобраться в синтаксисе.

Paul Nathan 28.03.2009 19:25

Другие вопросы по теме