如何将 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# 类的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 jQuery 将数据从 PHP 加载到 Handsontable?
handsontable:如何将整个数据行(对象)用作热列的数据?
如何将 Handsontable 数据发布到 WordPress REST API?