«Аўтаматычны» перанос табліцы SQL Server ў F # матрыцы

У мяне ёсць наступны код, які робіць імпарт з SQL ў F # і пераклад інфармацыі ў матрыцу.

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

Гэта рашэнне працуе, але я павінен праверыць ўручную эвалюцыі ў табліцы SQL і ўручную змяніць назву слупкоў у маім кодзе, які будзе хутка вельмі балючы. Так што маё пытанне:

Ці бачыце вы спосаб мець памеры табліцы SQL аўтаматычна прыняты пад увагу і ў больш агульным выпадку, у вас ёсць спосаб зрабіць гэта імпарт без неабходнасці пісаць ўручную імя кожнага слупка ( «Criteria0_ID» і г.д., назва Стоўбцы ў SQL ")? Thks загадзя!

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

2 адказы

Выкарыстанне 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
3
дададзена
Гэта можа быць вельмі добры адказ, я проста памылка, я не разумею: ExecuteReader мае патрэбу ў адкрытай і Availabe Connection. Злучэнне фактычна зачыненая. Гэтая памылка, здаецца, ставяцца да C: \ PRG \ FsSql \ FsSql \ FsSql.fs: радок 193 і C: \ PRG \ FsSql \ FsSql \ FsSql.fs: радок 203.
дададзена аўтар katter75, крыніца
Ды, дзякуй я гэта выправіў, цяпер новая памылка кажа: Указаны кідок не дзейнічае (памылка, здаецца, зыходзіць з execReader)
дададзена аўтар katter75, крыніца
Ён працуе вялікі дзякуй!
дададзена аўтар katter75, крыніца
Проста яшчэ адно пытанне: калі ў табліцы SQL У мяне ёсць значэння «NULL» (г.зн. карыстальнік не адказаў на пытанне), я магу адступіць яго мець нулі на маёй матрыцы? (На дадзены момант у мяне такая ж памылка «паказаная адліваная не дзейнічае», як толькі ў мяне ёсць «NULL» у SQL)
дададзена аўтар katter75, крыніца
Вялікі дзякуй, гэта працуе выдатна!
дададзена аўтар katter75, крыніца
@ Katter75: Я забыўся адкрыць злучэнне. Адрэдагаваны мой адказ, каб выправіць гэта.
дададзена аўтар Mauricio Scheffer, крыніца
@ Katter75: Я не ведаю, як які тып базы дадзеных спрабуе прачытаць поля. Гэты код спрабуе прачытаць іх непасрэдна як паплаўкі. Вы можаце паспрабаваць чытаць іх, як паміж першым, а затым пераўтвараць іх у плаваюць.
дададзена аўтар Mauricio Scheffer, крыніца
@ Katter75: напрыклад, замест Seq.cast у Seq.cast >> Seq.map усплываюць
дададзена аўтар Mauricio Scheffer, крыніца
@ Katter75: адрэдагавана зноў мець справу з гэтай справай.
дададзена аўтар Mauricio Scheffer, крыніца

У бягучай версіі F #, вы заўсёды павінны вызначыць карыстальніка увядзіце сябе. Вы можаце зрабіць некалькі трукаў, каб зрабіць капіраванне лепш. Прасцей за ўсё зрабіць, гэта выкарыстоўваць аператар, каб атрымаць наступны сінтаксіс:

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 (праект) дакументацыі .

1
дададзена