«Автоматический» перевод таблицы SQL Server в матрицу F # - PullRequest
2 голосов
/ 28 октября 2011

У меня есть следующий код, который выполняет импорт из SQL в F # и переводит информацию в матрицу.

У меня есть пример пользователей, имеющих 4 критерия, но если я хочу добавить еще 2 критерия, например (и количество критериев может измениться), мне придется сделать это вручную (в этом коде измерение не выполняется автоматически и названия столбцов должны быть написаны).

Это решение работает, но я должен вручную проверить эволюцию в таблице SQL и вручную изменить имя столбцов в моем коде, что вскоре будет очень болезненным. Итак, мой вопрос:

Видите ли вы способ автоматического учета размеров таблицы SQL и, в более общем смысле, есть ли способ выполнить этот импорт без необходимости вручную писать имя каждого столбца ("Criteria0_ID" и т. Д. название колонки в SQL ")? Заранее спасибо!

type user = {
    Criteria0_ID :  int;
    Criteria1_ID : int;
    Criteria2_ID : int;
    Criteria3_ID : int}

// Extraction from SQL

module ReadSQl =

    let GetUsers = seq { 
        let connStr = new SqlConnectionStringBuilder(DataSource="localhost\sqlexpress", IntegratedSecurity=true, InitialCatalog="TestExtractionF#")
        use cnn = new SqlConnection(connStr.ConnectionString)
        use cmd = new SqlCommand("SELECT * FROM SyntheseTest", cnn)
        cnn.Open()

        use reader = cmd.ExecuteReader()
        while reader.Read() do
        yield {
               Criteria0_ID = unbox(reader.["Criteria0_ID"])
               Criteria1_ID = unbox(reader.["Criteria1_ID"])
               Criteria2_ID = unbox(reader.["Criteria2_ID"])
               Criteria3_ID = unbox(reader.["Criteria3_ID"])
               }
         }

// Sequence transformation

let UserBase = GetUsers |> Seq.toList

// Creating the matrix

let matrixUA =
    Matrix.ofList
        [ // Create list containing rows from the database
        for row in UserBase do
      // For each row, return list of columns (float values)
            yield [ float row.Criteria0_ID; 
                    float row.Criteria1_ID;
                    float row.Criteria2_ID;
                    float row.Criteria3_ID;
                                    ] ]

matrixUA

Ответы [ 2 ]

3 голосов
/ 29 октября 2011

Используя FsSql , вы можете написать что-то вроде этого:

let readMatrixUA() =
    let connStr = SqlConnectionStringBuilder(DataSource="localhost\sqlexpress", IntegratedSecurity=true, InitialCatalog="TestExtractionF#")
    use cnn = new SqlConnection(connStr.ConnectionString)
    cnn.Open()
    Sql.execReader (Sql.withConnection cnn) "select * from SyntheseTest" []
    |> Sql.map Sql.asNameValue
    |> Seq.map (Seq.map (snd >> Option.fromDBNull >> Option.getOrDefault >> float))
    |> Matrix.ofSeq
1 голос
/ 28 октября 2011

В текущей версии F # вам всегда нужно определять тип user самостоятельно.Вы можете сделать несколько трюков, чтобы сделать копирование приятнее.Проще всего использовать оператор ? для получения следующего синтаксиса:

let (?) (reader:SqlDataReader) (name:string) : 'T =
  unbox (reader.[name])

 yield { Criteria1_ID = reader?Criteria1_ID
         Criteria2_ID = reader?Criteria2_ID 
         Criteria3_ID = reader?Criteria3_ID }

Вы можете пойти еще дальше - если вы откроете Microsoft.FSharp.Reflection, вы можете использовать FSharpType.GetRecordFields, чтобы получитьИмена полей (с помощью отражения) и выполнять копирование динамически - если вы используете этот подход, вам нужно будет только изменить объявление записи.Это, вероятно, насколько вы можете получить с текущей версией F #.

Однако F # 3.0 (в Visual Studio 11) содержит функцию, называемую тип поставщика , которая по существу позволяет импортироватьсхема автоматически.Вы можете узнать больше из выступлений Дона Сайма (см. , например, ) и из MSDN (черновой) документации .

.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...