【问题标题】:Generic conversion of record array to DataTable and vice versa in F#在 F# 中记录数组到 DataTable 的通用转换,反之亦然
【发布时间】:2012-10-05 07:47:31
【问题描述】:

我有以下类型的简单 F# 记录数组(或依赖于系统类型的一些小变化):

type Transaction= {
    date: DateTime;
    amount: float;
    mutable details: string }

我想将它们显示到 Winforms 中的 DataGridView 控件,包括支持更改内容以及添加或删除行/记录。将 DataViewGrid 绑定到记录数组似乎不允许添加/删除行(或者我一定做错了吗?)。然而,DataTable 结构似乎更适合此目的。创建上述类型的 DataTable 似乎与原始记录类型非常匹配,例如:

let dataTable = new DataTable()
    dataTable.Columns.Add("date", typeof<DateTime>) |> ignore
    dataTable.Columns.Add("amount", typeof<float>) |> ignore
    dataTable.Columns.Add("details", typeof<string>) |> ignore)

所以我想知道是否有一个现有的系统函数可以将依赖于系统类型的任何类型的记录的记录数组(例如,键入“事务数组”)转换为相应的 DataTable,反之亦然?如果没有这样的功能,怎么能简洁明了呢?

【问题讨论】:

    标签: datagridview datatable f#


    【解决方案1】:

    没有内置函数。

    实现转换的最直接方法是使用 F# 反射,但天真地使用反射(像这样)可能会很慢,因此您应该衡量性能是否足以满足您的要求(如果这是在 UI 中显示内容的一次性转换,这可能还不错)。

    这是你如何做到这一点的草图:

    open Microsoft.FSharp.Reflection
    
    let recordsToDataTable (items:'T list) =
      // Create data table and add fields based on the record type
      let dataTable = new DataTable() 
      let fields = FSharpType.GetRecordFields(typeof<'T>)
      for fld in fields do
        dataTable.Columns.Add(fld.Name, fld.PropertyType) |> ignore
      // Add values from the specified list to the table
      for itm in items do
        let row = dataTable.NewRow()
        // Set all fields of the current row
        for fld in fields do
          row.[fld.Name] <- fld.GetValue(itm)
        dataTable.Rows.Add(row)
      dataTable      
    
    let dataTableToRecords (table:DataTable) : 'T list =
      let fields = FSharpType.GetRecordFields(typeof<'T>)
      // Create a list with item for every row in the table
      [ for row in table.Rows ->
          // Get values of all fields from DT and create a record value
          let values = [| for fld in fields -> row.[fld.Name] |]
          FSharpValue.MakeRecord(typeof<'T>, values) :?> 'T ]
    

    【讨论】:

    • 您如何解释 excel 中可能没有值的 DateTime 列?这在使用DateTime optionNullable&lt;DateTime&gt; 时出现了。对于小数列也会在 decimal option 上抛出 =(
    猜你喜欢
    • 2023-04-03
    • 1970-01-01
    • 2020-04-08
    • 2015-02-16
    • 1970-01-01
    • 2011-09-23
    • 2012-06-15
    • 1970-01-01
    相关资源
    最近更新 更多