如何将 Handsontable 数据转换回 C# 类

Posted

技术标签:

【中文标题】如何将 Handsontable 数据转换回 C# 类【英文标题】:How to convert Handsontable data back into C# class 【发布时间】:2016-03-12 07:58:39 【问题描述】:

我正在使用 ajax 帖子将我的列标题和数据从掌上电脑发送回 ashx 处理程序。

   $.ajax(
       type: 'POST',
       url: "Scripts/SaveExcelData.ashx",
       contentType: "application/json; charset=utf-8",
       data: JSON.stringify("columns": hot.getColHeader(), "rows": hot.getData()),
       success: function (data) 
   );

目前我正在使用跟随来反序列化请求,但未能成功提出任何将行转换为 DataBaseRow 类对象数组的方法。

var jsonString = String.Empty;
context.Request.InputStream.Position = 0;
using (var inputStream = new StreamReader(context.Request.InputStream))

    jsonString = inputStream.ReadToEnd();
    var results = JsonConvert.DeserializeObject<dynamic>(jsonString);
    var columns = results.columns;
    var rows = results.rows;

    //use columns here to convert rows into DataBaseRow class

列看起来像:["Col1","Col2","Col3"] 行看起来像:[["Val1","Val2","Val3"],["Val1","Val2","Val3"],["Val1","Val2","Val3"]]

我该怎么做?

更新 我发现我实际上可以手动循环遍历数组值并将它们写入 DataBaseRow 类的新实例,而不是尝试将动态类转换为 DataBaseRow 类。

using (DBEntities edmx = new DBEntities())

    foreach (var row in rows)
    
        DataBaseRow dbr = new DataBaseRow();
        edmx.DataBaseRow.Add(dbr);
        dbr.LoadedTime = DateTime.Now;

        for (int i = 0; i < row.Count; i++)
        
            string colval = row[i].ToString();
            string colname = columns[i].ToString();
            switch (colname)
            
                case "Col1":
                    dbr.DBCol1 = colval;
                    break;
                case "Col2":
                    dbr.DBCol2 = colval;
                    break;
                case "Col3":
                    dbr.DBCol3 = colval;
                    break;
            
        
    
    edmx.SaveChanges();

这可行,但速度很慢(请参阅时间评论)。是否有更快/更好的方法来处理这些数据? (如果重要的话 - 我实际上有 14 列要映射到开关中)

【问题讨论】:

您是否考虑过编写一个循环来添加列定义,然后再编写一个循环来添加每一行? 我可以通过手动循环 JArray 值来使其工作。请参阅上面的更新问题。 一个 5000 条记录的数据集总共只用了 4 分钟多一点(发送时间,FOREACH 循环约 1.5 分钟,SaveChanges 调用约 2 分钟)。一个 50000 条记录的数据集只运行了大约 2 个小时。缓慢处理所有数据似乎还不错,但是当它尝试调用 SaveChanges 时给了我一个内存不足错误。 1.无需在最内层循环中查找列名。如果您需要读取第一行以获取列名,请在 foreach 循环的第一次迭代中执行此操作。否则在 foreach 循环之外执行。你要多做 4,999 次。这让你付出了代价。 2. 表是一组具有给定列结构的行。在 foreach 之外创建一个表,并将每一行添加到其中。从逻辑上讲,这是一张表中的 5,000 行。我的猜测是,创建 4,999 个额外的表并将每一个表添加到 edmx 可能会让你丧命。我敢打赌这是 50k 行的内存问题。 我在移动大数据时遇到了实体框架的速度问题,因为往返行程加起来。我转而使用SqlBulkCopy 进行批量导入,这样更快。 【参考方案1】:

所以我的问题的技术答案可以在我添加的更新中找到(只需将动态对象引用为数组,不要尝试转换它们)。

但是,Entity Framework 在处理保存大型数据集方面似乎很差。这可以通过将保存分组并为每个块重新创建上下文来加快速度。 https://***.com/a/5942176/266592

我最终重写了它以将值插入DataTable,然后使用SqlBulkCopy 将记录保存到数据库中。

var jsonString = String.Empty;
context.Request.InputStream.Position = 0;
using (var inputStream = new StreamReader(context.Request.InputStream))

    jsonString = inputStream.ReadToEnd();
    var results = JsonConvert.DeserializeObject<dynamic>(jsonString);
    var columns = results.columns;
    var rows = results.rows;

    var dt = new DataTable();
    for (int i = 0; i < columns.Count; i++)
            
        dt.Columns.Add(columns[i].ToString());
    

    foreach (var row in rows)
    
        var datarow = dt.NewRow();
        for (int i = 0; i < row.Count; i++)
        
            datarow[i] = row[i];
        
        dt.Rows.Add(datarow);
    

    using (var connection = new SqlConnection(ConnectionString))
    
        SqlTransaction transaction = null;
        connection.Open();
        try
        
            transaction = connection.BeginTransaction();
            using (var sqlBulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.TableLock, transaction))
            
                sqlBulkCopy.DestinationTableName = "TABLENAME";
                sqlBulkCopy.BatchSize = 100000;
                sqlBulkCopy.BulkCopyTimeout = 0;
                foreach (DataColumn col in dt.Columns)
                
                    sqlBulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName);
                
                sqlBulkCopy.WriteToServer(dt);
            
            transaction.Commit();
        
        catch (Exception)
        
            transaction.Rollback();
        
    

【讨论】:

以上是关于如何将 Handsontable 数据转换回 C# 类的主要内容,如果未能解决你的问题,请参考以下文章

Handsontable:如何将数据发布为关联数组

如何使用 jQuery 将数据从 PHP 加载到 Handsontable?

handsontable:如何将整个数据行(对象)用作热列的数据?

如何将 Handsontable 数据发布到 WordPress REST API?

当使用 WinForms 提取数据时,XML 会转换为纯文本。有没有办法维护 XML,或将其转换回 C#?

如何将默认值 0 赋予 Handsontable 中的所有空单元格?