Search code examples
c#datatableenumerable

Filtering DataTable and copying results to two different DataTables


I'm trying to filter results from a method that returns a DataTable, by a certain column value (of type DateTime) and inserting them into two distinct DataTables, as follows:

var vAllItems = myClass.GetAllResults(x,y,z);
DataTable dtExpiredItems = new DataTable();
DataTable dtActiveItems = new DataTable();

var expiredItems = vAllItems.AsEnumerable().Where(r => r.Field<DateTime?>("ExpDate") <= DateTime.Now && r.Field<DateTime?>("ExpDate").HasValue);
var activeItems = vAllItems.AsEnumerable().Where(r => r.Field<DateTime?>("ExpDate") > DateTime.Now || !r.Field<DateTime?>("ExpDate").HasValue);

foreach(DataRow row in expiredItems)
     dtExpiredItems.Rows.Add(row);

foreach (DataRow row in activeItems)
     dtActiveItems.Rows.Add(row);

rptExpiredItems.DataSource = dtExpiredItems;
rptExpiredItems.Bind();
pchExpiredItems.Visible = dtExpiredItems.Rows.Count > 0;

rptActiveItems.DataSource = dtActivetItems;
rptActiveItems.Bind();
pchActiveItems.Visible = dtActiveItems.Rows.Count > 0;

Thing is, on the second foreach loop the following error occurs:

This row already belongs to another table.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.ArgumentException: This row already belongs to another table.

Any help is appreciated! Thanks!


Solution

  • A DataRow can only belong to a one DataTable, you should create a new row from given row values.

    Use ItemArray property of the DataRow to get values and pass object[] as an input to create new row.

    dtExpiredItems.Rows.Add(row.ItemArray);
    

    or use ImportRow

    dtExpiredItems.ImportRow(row);
    

    Another option is using CopyToDataTable (DataTable)extension to create new table from Linq output, then use new table for your binding.

    dtExpiredItems = expiredItems.CopyToDataTable<DataRow>();