2016-11-13 2 views
1

Im пытается заполнить список своим собственным типом.Список заполнения с помощью типов

let getUsers = 
    use connection = openConnection() 
    let getString = "select * from Accounts" 
    use sqlCommand = new SqlCommand(getString, connection) 
    try 
     let usersList = [||] 
     use reader = sqlCommand.ExecuteReader() 
     while reader.Read() do 
      let floresID = reader.GetString 0 
      let exName = reader.GetString 1 
      let exPass = reader.GetString 2 
      let user = [floresID=floresID; exName=exName; exPass=exPass] 
      // what here? 
      () 
    with 
     | :? SqlException as e -> printfn "Došlo k chybě úrovni připojení:\n %s" e.Message 
     | _ -> printfn "Neznámá výjimka." 

В C# я бы просто добавить новый объект в userList. Как добавить новый список user? Или это лучший подход, чтобы получить какой-то список с данными из базы данных?

+3

Если вы уже можете получить нужный вам список из базы данных, это, вероятно, будет лучшим способом. Кроме этого, вы можете использовать 'ResizeArray <_>', который представляет собой .NET. System.Collections.Generic.List <_> '. 'usersList' в настоящее время является массивом, а массивы никогда не могут быть добавлены в .NET. – TeaDrivenDev

+0

Какую базу данных вы используете, и есть ли конкретная причина использовать ADO? Вы должны попытаться получить доступ к нему с помощью поставщика типа. В любом случае вместо массива попробуйте вернуть sqq (IEnumerable) записей. – s952163

ответ

2

Самый простой способ сделать это с помощью поставщика типа, чтобы вы могли абстрагироваться от базы данных. Вы можете использовать SqlDataConnection для SQLServer, SqlProvider для всего (включая SQLServer), а также SQLClient для SQLServer.

Вот пример с dvdrental Postgres (в образце) базы данных для SQLProvider:

#r @"..\packages\SQLProvider.1.0.33\lib\FSharp.Data.SqlProvider.dll" 
#r @"..\packages\Npgsql.3.1.8\lib\net451\Npgsql.dll" 

open System 
open FSharp.Data.Sql 
open Npgsql 
open NpgsqlTypes 
open System.Linq 
open System.Xml 
open System.IO 
open System.Data 

let [<Literal>] dbVendor = Common.DatabaseProviderTypes.POSTGRESQL 
let [<Literal>] connString1 = @"Server=localhost;Database=dvdrental;User Id=postgres;Password=root" 
let [<Literal>] resPath = @"C:\Users\userName\Documents\Visual Studio 2015\Projects\Postgre2\packages\Npgsql.3.1.8\lib\net451" 
let [<Literal>] indivAmount = 1000 
let [<Literal>] useOptTypes = true 

//create the type for the database, based on the connection string, etc. parameters 
type sql = SqlDataProvider<dbVendor,connString1,"",resPath,indivAmount,useOptTypes> 
//set up the datacontext, ideally you would use `use` here :-) 
let ctx = sql.GetDataContext() 
let actorTbl = ctx.Public.Actor //alias the table 

//set up the type, in this case Records: 
type ActorName = { 
    firstName:string 
    lastName:string} 

//extract the data with a query expression, this gives you type safety and intellisense over SQL (but also see the SqlClient type provider above): 
let qry = query { 
      for row in actorTbl do 
      select ({firstName=row.FirstName;lastName=row.LastName}) 
       } 
//seq is lazy so do all kinds of transformations if necessary then manifest it into a list or array: 
qry |> Seq.toArray 

две важные части определения записи Actor, а затем в запросе извлечения полей в последовательности Actor записей. Затем вы можете проявить себя в списке или массиве.

Но вы также можете придерживаться своего оригинального решения. В этом случае просто обернуть .Read() в seq:

Сначала определяют тип:

type User = { 
    floresID: string 
    exName: string 
    exPass: string 
} 

Затем извлечь данные:

let recs = cmd.ExecuteReader() // execute the SQL Command 
//extract the users into a sequence of records: 
let users = 
    seq { 
     while recs.Read() do 
      yield {floresID=recs.[0].ToString() 
        exName=recs.[1].ToString() 
        exPass=recs.[2].ToString() 
        } 
     } |> Seq.toArray 
1

Принимая код, вы можете использовать выражение списка:

let getUsers = 
    use connection = openConnection() 
    let getString = "select * from Accounts" 
    use sqlCommand = new SqlCommand(getString, connection) 
    try 
     [ 
      use reader = sqlCommand.ExecuteReader() 
      while reader.Read() do 
       let floresID = reader.GetString 0 
       let exName = reader.GetString 1 
       let exPass = reader.GetString 2 
       let user = [floresID=floresID; exName=exName; exPass=exPass] 
       yield user 
     ] 
    with 
     | :? SqlException as e -> failwithf "Došlo k chybě úrovni připojení:\n %s" e.Message 
     | _ -> failwithf "Neznámá výjimka." 

Это, как говорится, я бы использовал FSharp.Data.SqlClient libra поэтому вся эта плита котла станет одной линией с дополнительным преимуществом безопасности типа (если вы измените запрос, код будет иметь ошибку времени компиляции, которые очевидны для исправления).

Смежные вопросы