[英]Adding row into DataTable
如何通過從 csv 讀取記錄在沒有 foreach 循環的情況下將行添加到數據表中?
var records = File.ReadLines(FD.FileName, Encoding.UTF8).Skip(1);
//not working because datatable is not thread safe
Parallel.ForEach(records, record => dataTable.Rows.Add(record.Split(',')));
//using for each is taking aroung 13 sec for 45000 records, need a better solution than this.
foreach (var record in records)
{
dataTable.Rows.Add(record.Split(','));
}
您是否嘗試過使用像 LINQ 到 CSV 這樣的庫?
我最近用過它,它非常好。
基本上你在你的 class 中設置結構如下
using LINQtoCSV;
using System;
class Product
{
[CsvColumn(Name = "ProductName", FieldIndex = 1)]
public string Name { get; set; }
[CsvColumn(FieldIndex = 2, OutputFormat = "dd MMM HH:mm:ss")]
public DateTime LaunchDate { get; set; }
[CsvColumn(FieldIndex = 3, CanBeNull = false, OutputFormat = "C")]
public decimal Price { get; set; }
[CsvColumn(FieldIndex = 4)]
public string Country { get; set; }
[CsvColumn(FieldIndex = 5)]
public string Description { get; set; }
}
之后使用下面的代碼讀取文件
CsvFileDescription inputFileDescription = new CsvFileDescription
{
SeparatorChar = ',',
FirstLineHasColumnNames = true
};
CsvContext cc = new CsvContext();
IEnumerable<Product> products =
cc.Read<Product>("products.csv", inputFileDescription);
// Data is now available via variable products.
var productsByName =
from p in products
orderby p.Name
select new { p.Name, p.LaunchDate, p.Price, p.Description };
// or ...
foreach (Product item in products) { .... }
讓我知道事情的后續
我敢肯定,您不需要一次顯示 50000 行。 僅僅因為這不是人類可讀的。
考慮分頁:加載前 N 行,然后,當用戶單擊“下一頁”按鈕時,加載下 N 行,依此類推。
將這個 class 作為數據行:
public class MyDataRow
{
public int Id { get; set; }
public string Name { get; set; }
}
分頁演示將是這樣的:
public partial class Form1 : Form
{
private const int PageSize = 10;
private readonly BindingList<MyDataRow> dataRows;
private readonly IEnumerator<string> csvLinesEnumerator;
public Form1()
{
InitializeComponent();
// start enumeration
csvLinesEnumerator = ReadLines().Skip(1).GetEnumerator();
// assign data source to DGV
dataRows = new BindingList<MyDataRow>();
dataGridView1.DataSource = dataRows;
// fetch first page
FetchNextPage();
}
private void button1_Click(object sender, EventArgs e) => FetchNextPage();
private void FetchNextPage()
{
// disable notifications
dataRows.RaiseListChangedEvents = false;
try
{
dataRows.Clear();
while (dataRows.Count < PageSize)
{
if (csvLinesEnumerator.MoveNext())
{
// parse next line and make row object from line's data
var lineItems = csvLinesEnumerator.Current.Split(',');
var row = new MyDataRow
{
Id = int.Parse(lineItems[0]),
Name = lineItems[1]
};
// add next row to the page
dataRows.Add(row);
}
else
{
break;
}
}
}
finally
{
// enable notifications and reload data source into DGV
dataRows.RaiseListChangedEvents = true;
dataRows.ResetBindings();
}
}
/// <summary>
/// This is just File.ReadLines replacement for testing purposes
/// </summary>
private IEnumerable<string> ReadLines()
{
for (var i = 0; i < 50001; i++)
{
yield return $"{i},{Guid.NewGuid()}";
}
}
}
用戶界面:
另一種選擇是使用DataGridView.VirtualMode
,但它主要針對某些情況進行了優化,當您知道總行數時(例如,您可以通過 SQL 查詢對它們進行計數),但對於 CSV 文件則不是這樣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.