2

我试图用我自己的类型填充列表。

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到列表中?还是从数据库中获取某种包含数据的列表的更好方法?

4

2 回答 2

2

最简单的方法是使用类型提供程序,因此您可以抽象出数据库。您可以将SqlDataConnection用于 SQLServer,将 SqlProvider用于所有内容(包括 SQLServer),还可以将SQLClient用于 SQLServer。

下面是一个用于 SQLProvider 的 postgres dvdrental(示例)数据库示例:

#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
于 2016-11-14T02:21:51.547 回答
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 库,因此所有样板都变成了一行,并增加了类型安全的好处(如果您更改查询,代码将出现编译时错误,这是显而易见的修复) .

于 2016-11-15T00:50:33.560 回答