简体   繁体   English

最快的方式来更新所有行,使其在datatable中的一列中具有相同的值,而不在C#中进行循环

[英]Fastest way to update all rows to have same value in one column in datatable, without loop in C#

I have datatable "users" and column "is_published" in it. 我有数据表“users”和列“is_published”。 I have about 100k rows. 我有大约100k行。 What is the fastest way to update value in the column, so the whole rows in column have same value = 1. 更新列中值的最快方法是什么,因此列中的整行具有相同的值= 1。

I try with classic foreach loop and it't slow, also I try with LINQ : 我尝试使用经典的foreach循环而且速度不慢,我也尝试使用LINQ:

dsData.Tables["users"].Select().ToList().ForEach(x => x["is_published"] = 1;);

and it still isn't fast enough. 它仍然不够快。

Also variant wit Expression doesn't work for me, because after that fields is ReadOnly and I can't change value again. 另外变体机智表达式对我不起作用,因为在该字段之后是ReadOnly并且我不能再次更改值。

This is C#. 这是C#。

when you create your table you can simply push a default value to your column.. 创建表时,只需将默认值推送到列中即可。

 DataTable dt = new DataTable();
dt.Columns["is_published"].DataType = System.Int32;
dt.Columns["is_Published"].DefaultValue = 1;

then when you need to change the rows to default value ( or will you need? ) 然后当你需要将行更改为默认值(或者你需要?)

// Say your user selects the row which its index is 2..
// The ItemArray gives the selectedRow's cells as object..
// And say your columns index no is 5..
dt.Rows[2].ItemArray[5] = default ;

or 要么

dt.Rows[2].ItemArray[5] = dt.Columns["is_published"].DefaultValue;

Separate the select and the update into two operations. 选择更新分成两个操作。 Skip the ToList() operation and instead iterate afterwards over the IEnumerable collection using forEach and update the value: 跳过ToList()操作,然后使用forEachIEnumerable集合上迭代并更新值:

var rows = dsData.Tables["users"].Select();
forEach(var row in rows)
{
    row["is_published"] = 1;
}

The ToList forces an immediate query evaluation which in this case acts as a copy of all items from the IEnumerable collection, so you can gain some speed here. ToList强制立即进行查询评估 ,在这种情况下,它作为IEnumerable集合中所有项目的副本,因此您可以在这里获得一些速度。 I ran some tests and the result in this case is (using your code and the modification): ToList is 3 times slower than iterating over IEnumerable and single update! 我运行了一些测试,在这种情况下的结果是(使用你的代码和修改): ToList比迭代IEnumerable和单个更新慢3倍

IMO 40 seconds is an awful lot for 100K items. 对于100K物品,IMO 40秒非常多。 If your DataTable is bound to a DataGridView or some other UI control, i believe that the update of the GUI is taking so long and not the update of the values itself. 如果您的DataTable绑定到DataGridView或其他一些UI控件,我相信GUI的更新需要很长时间,而不是更新值本身。 In my tests the update using ToList took fractions of a second (on my simple Lenovo netbook with AMD E-450 processor, and i assume you are not using a 386 machine). 在我的测试中,使用ToList的更新花了不到一秒钟(在我的简单联想上网本上使用AMD E-450处理器,我假设你没有使用386机器)。 Try suspending the UI bevor updating and refreshing the values and then enable it again - example in this SO post . 尝试暂停UI bevor更新并刷新值,然后再次启用它 - 例如在此SO帖子中


My original post (as i can see you gained some speed using the code - interesting): 我的原帖(因为我可以看到你使用代码获得了一些速度 - 有趣):

More an experiment for my part, but it is possible to: 对我来说更多的实验,但有可能:

  • convert the table to XML 将表转换为XML
  • fetch all elements that should be changed 获取应该更改的所有元素
  • change them 改变它们
  • write the changed XML back to the table 将更改后的XML写回表中

The code: 编码:

// temp table
var dataTable = new DataTable("Table 1");
dataTable.Columns.Add("title", typeof(string));
dataTable.Columns.Add("number", typeof(int));
dataTable.Columns.Add("subnum1", typeof(int));
dataTable.Columns.Add("subnum2", typeof(int));
// add temp data
Enumerable.Range(1, 100000).ToList().ForEach(e =>
{
    dataTable.Rows.Add(new object[] { "A", 1, 2, 3 });
});
// "bulk update"!
var sb = new StringBuilder();
var xmlWriter = XmlWriter.Create(sb);
dataTable.WriteXml(xmlWriter);
var xml = XDocument.Parse(sb.ToString());
// take column to change
var elementsToChange = xml.Descendants("title").ToList();
// the list is referenced to the XML, so the XML is changed too!
elementsToChange.ForEach(e => e.Value = "Z");
// clear current table
dataTable.Clear();
// write changed data back to table
dataTable.ReadXml(xml.CreateReader());

The table is updated. 该表已更新。 IMO the parts that make this solution slow are the IMO使这个解决方案变慢的部分是

  • convertion from and to XML 从XML转换到XML
  • and the fill of the StringBuilder 和StringBuilder的填充

The other way around the pure update of the list is probably faster than the table update. 纯粹更新列表的另一种方法可能比表更新更快。

Finaly! Finaly! I speed up update so it takes 2-3 sec. 我加快更新速度,所以需要2-3秒。 I added BeginLoadData() and EndLoadData() 我添加了BeginLoadData()和EndLoadData()

    DataTable dt = ToDataSet().Tables["users"];
    var sb = new StringBuilder();
    var xmlWriter = XmlWriter.Create(sb);
    dt.WriteXml(xmlWriter);
    var xml = XDocument.Parse(sb.ToString());
    xml.Descendants("is_published").ToList().ForEach(e => e.Value = "1");
    dt.Clear();
    dt.BeginLoadData();
    dt.ReadXml(xml.CreateReader());
    dt.EndLoadData();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM