2017-01-18 15 views
0

Я следующий DataTable.NET 4.0 Добавить одинаковые значения во всех строках для столбца в DataTable

DataTable dt = new dataTable(); 

Я получил эту DataTable, заполненный от некоторого другого метода. Он будет иметь 50000 строк и 40 столбцов перед выполнением следующих утверждений.

Количество строк и столбцов может отличаться. поэтому я не определил конкретный набор столбцов в dataTable.

Я хочу добавить два столбца в конец (guid и adddate) и хочу добавить одинаковое значение во все строки 50K для этих двух столбцов.

Я написал простой цикл foreach для этого. Есть ли способ, которым я могу это сделать Parallely?

Я пробовал использовать Parallel.Foreach, но не получил никакого успеха.

//by this time my dt will have 50000 rows and 40 columns 

dt.Columns.Add(new DataColumn("guid", typeof(string))); 
dt.Columns.Add(new DataColumn("addeddate", typeof(DateTime))); 
string sessionIDValue = Convert.ToString(Guid.NewGuid()); 
DateTime todayDt = DateTime.Today;     


foreach (DataRow row in dt.Rows) 
{ 
    row["guid"] = sessionIDValue; 
    row["addeddate"] = todayDt;  
} 
+0

Вы уже попробовать указав 'DefaultValue' для DataColumns вы добавляете? Я бы не посмел предсказать, насколько хорошо это работает (если оно даже работает). – Filburt

+0

@Filburt да, но поскольку структура DataTable не исправлена, мы не можем указать, что – captainsac

ответ

2

Вам необходимо получить доступ к строкам с использованием явных указателей, и индекс строки будет идеальным способом сделать это.

Вы должны иметь возможность создать массив, равный числу строк, которые у вас есть (например, 50000), с индексом для каждой строки в качестве значений этого массива (например, 0..1..2..3 .. и т. д.), а затем используйте параллельный цикл для этого массива индексов, посредством которого вы передаете явный индекс строки в объект dt.Rows.

Суть кода будет:

// Pseudo code 

// Create array equal to size of the # of rows (int ArrayOfIndexes[]) 
// Fill that array with values representing row indexes starting at 0 

Parallel.ForEach(ArrayOfIndexes, (index) => 
{ 
    lock(dt) 
    { 
     dt.Rows[index]["guid"] = sessionIDValue; 
     dt.Rows[index]["addeddate"] = todayDt; 
    } 
} 

EDIT: Я не узнал, что с DataTable не поточно-, что вы должны включить блокировку вокруг ваших заданий, которые, очевидно, дает производительность, но все равно должен быть быстрее, чем просто цикл без Parallel.ForEach.

+0

Я думаю, что здесь нет смысла использовать блокировку. И даже если вы этого захотите, лучше всего иметь отдельный lockObject. +1 для Parallel.ForEach –

+0

«Замок» должен был защищать от того, что вы получите прерывистые ошибки при присвоении значения строки, поскольку DataTable не является потокобезопасным. Согласился с вами, что отдельный объект блокировки - хорошая идея ... Я в основном просто давал «сущность» решения, а не точное решение. :) –

0

Обновление ответа @Shane Oborn без дополнительной переменной ArrayOfIndexes и использует отдельный объект блокировки.

Я хотел бы использовать:

var lockObj = new object(); 
Parallel.Foreach(dt.AsEnumerable(), row => 
{ 
    lock(lockObj) 
    { 
     row["guid"] = sessionIDValue; 
     row["addeddate"] = todayDt;  
    } 
}); 

Вы должны добавить используя операторы:

using System.Data.DataSetExtensions; 
using System.Linq; 
using System.Xml; 
+0

Это неправда Антон. Как я уже упоминал выше, если вы используете то, что у вас здесь, а затем попробуйте это на массиве, скажем, размером 5000, вы увидите, что вы получаете «индексные» ошибки из-за того, что DataTable не является потокобезопасным. –

+0

Я тестировал, и вы правы, кажется, что редактировать DataTable невозможно без блокировки. И блокировка устраняет все преимущества параллелизма в этом случае ... –

+0

Правильно, если приведенный выше код в конечном итоге является всем, что используется, тогда никакой выгоды не будет.Однако, если есть что-то еще, что может быть вне блокировки, очевидно, что в этом случае возникает какая-то польза, но только относительно объема работы, выполняемой вне блокировки. –