1

我有以下记录类型“tbl”,它将包含列表或序列。如何使用 f sharp 将这个“tbl”保存/更新到现有的访问数据库表中,字段名称如下所示。

type Tbl= {     P:string; 
                In:System.DateTime; 
                Ex:System.DateTime;
                B:string; 
                CC:string; 
                GG:double; 
                PR:double;
                DE:double;
                PRE:double; 
                DEU:double; 
                PRPL_DEDUC:double; 
                GUR:double; 
                GC:double; 
                PRP:double; 
                PDA:double; 
                PRO:double}

let conn = new OleDbConnection( @"Provider=Microsoft.ACE.OLEDB.12.0;
          Data Source=T:\Test.accdb;
           Persist Security Info=False;" )
conn.Open()    

let sql="INSERT INTO Test SELECT * FROM " Tbl
let DAdapter = new OleDbDataAdapter(sql,conn)
DAdapter.Update
4

2 回答 2

3

这里有几件事浮现在脑海中。

首先,我认为你在解释记录类型时遇到了麻烦——它不是一个记录集——所以你不能只输入一个 oledbdataadapter。

F# 类型提供程序中对 Access 的支持也不多 - 我不知道有多少,但作为示例 SqlProvider 允许您从 Access 读取但不执行 CRUD 操作。

所以,至少据我所知,你上面提到的老式 oledb 方法实际上是正确的路径。

下面的代码使用 SqlProvider 来检索具有 3 列的访问数据库的内容,saveARow 函数将不起作用,然后它继续以 oledb 方式进行操作...

#r @"packages\SQLProvider.0.0.9-alpha\lib\net40\FSharp.Data.SqlProvider.dll"

open System
open System.Linq
open FSharp.Data.Sql

[<Literal>]
let cnStr = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\temp\Database1.accdb;Persist Security Info=False;"

type sql = SqlDataProvider<
                ConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\temp\Database1.accdb;Persist Security Info=False;",
                DatabaseVendor = Common.DatabaseProviderTypes.MSACCESS>
let ctx = sql.GetDataContext()

// return some data
ctx.``[Database1].[Table1]`` |> Seq.take 1

// create a type to represent the data
type Row = {P: string; In:System.DateTime; GG:double}

// insert some more data P:string, In:datetime, Ex:datetime, B:string, GG:number
// unfortunately SqlDataProvider doesn't support CRUD operations on MS Access...
let saveARow (aRow: Row) =
    let table1 = ctx.``[Database1].[Table1]``.Create()
    table1.P <- aRow.P
    table1.In <- aRow.In
    table1.GG <- aRow.GG
    ctx.SubmitUpdates()

{P="abc"; In=DateTime.Now; GG=200.}
|> saveARow

// try it the old fashioned way
open System.Data
open System.Data.OleDb

#r @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.Transactions.dll"
open System.Transactions

let saveARow2(aRow: Row) =
    let cn = new OleDbConnection(cnStr)
    cn.Open()
    let cmd = new OleDbCommand()
    cmd.CommandType <- CommandType.Text
    let insertCmd = sprintf "insert into Table1 values ('%s', '%s', '%f')" aRow.P (aRow.In.ToShortDateString()) aRow.GG
    cmd.CommandText <- insertCmd
    cmd.Connection <- cn
    cmd.ExecuteNonQuery() |>ignore
    cn.Close()

{P="abcd"; In=DateTime.Now; GG=200.}
|> saveARow2
于 2015-06-28T08:43:55.313 回答
1

为什么序列不是数组或列表?也许更好地重写(我从你的另一个问题中获取数据):

type test = { G:double; P:double; GG:double; PP:double } 

let table = [for x in 0..(Un0.Length - 1) -> 
                let b = Un0.[x] in 
                if b=0.0 then {G=0.0; P=0.0; GG=0.0; PP=0.0}
                else {G=G_0.[x]/b; P=P0.[x]/b; GG=G0.[x]/b; PP=PP0.[x]/b}]

let str = @"Provider=Microsoft.ACE.OLEDB.12.0;
 Data Source=T:\Test.accdb;
 Persist Security Info=False;"

let conn = new OleDbConnection(str) 

let query text = 
    conn.Open() 
    use comm = conn.CreateCommand()
    comm.CommandText <- text
    comm.ExecuteNonQuery() |> ignore
    conn.Close()

let format = "INSERT INTO Test values ({0}, {1}, {2}, {3});"

table |> List.iter(fun x -> query (String.Format(format, x.G, x.P, x.GG, x.PP)))
于 2015-06-30T09:45:22.330 回答