Цей рядок вже належить до іншої помилки таблиці при спробі додати рядки?


197

У мене є DataTable, у якому є кілька рядків, і я використовую select, щоб відфільтрувати рядки, щоб отримати колекцію DataRows, яку я потім прокручую за допомогою foreach і додаю її до іншої DataTable, але це дає мені помилку "Цей рядок вже належить до іншої таблиці ". Ось код:

DataTable dt = (DataTable)Session["dtAllOrders"];
DataTable dtSpecificOrders = new DataTable();

DataRow[] orderRows = dt.Select("CustomerID = 2");

foreach (DataRow dr in orderRows)
{
    dtSpecificOrders.Rows.Add(dr); //Error thrown here.
}

1
велике запитання; Мене плутають рядки та таблиці, що належать до інших контейнерів
Вівіан-Рівер

Відповіді:


339

Вам потрібно створити нове Rowзі значеннями drспочатку. А DataRowможе належати лише одному DataTable.

Ви також можете використовувати, Addякий приймає масив значень:

myTable.Rows.Add(dr.ItemArray)

Або, можливо, навіть краще:

// This works because the row was added to the original table.
myTable.ImportRow(dr);

// The following won't work. No data will be added or exception thrown.
var drFail = dt.NewRow()
drFail["CustomerID"] = "[Your data here]";
// dt.Rows.Add(row); // Uncomment for import to succeed.
myTable.ImportRow(drFail);

6
Чи можна використовувати ImportRow як попереджувальний? і чому б .NET тільки не дозволяв вам мати однаковий DataRow для різних DataTables? Це за дизайном?
Xaisoft

3
Хе, я щойно зрозумів ImportRow, відредагував мою відповідь, і ти мене все побив. Але я рекомендую такий підхід, оскільки він скопіює рядок для вас
JoshBerke

2
ImportRowробота для мене. Але додав рядки! Thankssssssssssss
nawfal

1
ImportRow не буде працювати, якщо рядок, який ви імпортуєте, посилається на рядок у вихідній таблиці. ItemArray працює, якщо ви використовуєте вихідний рядок, але вам потрібно пам’ятати, що слід додати рядок до місця призначення, перш ніж ви видалите рядок із джерела, інакше він скаржиться, що рядок видалено та не може знайти дані.
Адам Холдсворт

2
.ImportRow()не працювало для мене, оскільки спочатку я не робив і не .Clone()створював стовпці на своєму новому DataTable. Він придумав 0, коли я подивився .Rows.Countна свій новий стіл. Оскільки мені потрібно було створити стовпчики в моїй таблиці та додати їх, я просто створив NewRow()оператор і додав свої значення до стовпців у новому рядку безпосередньо та додав цей рядок до моєї таблиці в циклі (див. Мою відповідь нижче) .
vapcguy

34

Спробуйте це:

DataTable dt = (DataTable)Session["dtAllOrders"];
DataTable dtSpecificOrders = dt.Clone();

DataRow[] orderRows = dt.Select("CustomerID = 2");

foreach (DataRow dr in orderRows)
{
    dtSpecificOrders.ImportRow(dr);
}

3
Дякую за це .. хоча відповідь, надана @JoshBerke, була правильною, вам потрібно клонувати оригінальну таблицю, як у вашому прикладі, щоб вона працювала.
carny666

8
yourTable.ImportRow(dataRow);

Це тому, що рядок, який ви копіюєте, не має однакового TableName:

Наприклад, спробуйте:

Table1.TableName = "Table1";
Table2.TableName = "Table2";

1
У мене був і неправильно названий стіл. Дякую!
Бруно

3
foreach (DataRow dr in dtSpecificOrders.rows)
{
   dtSpecificOrders.Rows.Add(dr.ItemArray); 
}

1
Я не думаю, що ви можете додати що-небудь до того, що ви повторюєте, як ви повторюєте це.
vapcguy

3

Це не найчистіше / швидке / найпростіше / найелегантніше рішення, але я створив грубу силу, щоб виконати роботу за аналогічним сценарієм:

DataTable dt = (DataTable)Session["dtAllOrders"];
DataTable dtSpecificOrders = new DataTable();

// Create new DataColumns for dtSpecificOrders that are the same as in "dt"
DataColumn dcID = new DataColumn("ID", typeof(int));
DataColumn dcName = new DataColumn("Name", typeof(string));
dtSpecificOrders.Columns.Add(dtID);
dtSpecificOrders.Columns.Add(dcName);

DataRow[] orderRows = dt.Select("CustomerID = 2");

foreach (DataRow dr in orderRows)
{
    DataRow myRow = dtSpecificOrders.NewRow();  // <-- create a brand-new row
    myRow[dcID] = int.Parse(dr["ID"]);
    myRow[dcName] = dr["Name"].ToString();
    dtSpecificOrders.Rows.Add(myRow);   // <-- this will add the new row
}

Імена в стовпцях даних повинні відповідати назвам у вашій початковій таблиці, щоб вона працювала. Я просто використав "Ідентифікатор" та "Ім'я" в якості прикладів.


1

Чому ви просто не використовуєте CopyToDataTable

DataTable dt = (DataTable)Session["dtAllOrders"];
DataTable dtSpecificOrders = new DataTable();

DataTable orderRows = dt.Select("CustomerID = 2").CopyToDataTable();

1
Що тут має бути OrderRows?
Аві

Нова таблиця даних для вибраних рядків з dtAvi.
vapcguy

0

ви можете надати деякий ідентифікатор стовпцям і однозначно назвати його.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.