Exception in copying DataRow to another DataTable - c#

I have two data tables, dt1 & dt2. dt1 has data while dt2 is a new table. Now I want to copy some rows, satisfying particular condition, to dt2. I have tried following code, but I get this exception:
System.ArgumentException This row already belongs to another table.
foreach(DataRow dr in dt1.Rows)
{
if(Convert.ToInt32(dr["col"]) == value)
{
dt2.Rows.Add(dr);
}
}
How can I resolve this?

change dt2.Rows.Add(dr); to dt2.Rows.Add(dr.ItemArray);

You directly cannot "Add" a DataTable row from one to another since it belongs to souce Datatable. You can "Add" a newly created row to DataTable.
Hence you are getting this exception.
There are many ways to overcome this. Some are listed below
Method 1:
If you want to get a row from source Datatable and add in destination without any changes, then use ImportRow this way.
dt2.ImportRow(dr);
Method 2:
But if you want to take specific data. Then use this
foreach(DataRow dr in dt1.Rows)
{
if(Convert.ToInt32(dr["col"]) == value)
{
Datarow ndr = dt2.NewRow();
ndr["Foo"] = dr["Foo"];
//..Similarly for other rows.
dt2.Rows.Add(ndr);
}
}

Every time when you add a row to the datatable it should be different(new) row........
Datarow newRow = null;
foreach(DataRow dr in dt1.Rows)
{
if(Convert.ToInt32(dr["col"]) == value)
{
newRow = dt2.NewRow();
newRow ["A"] = dr["A"];
dt2.Rows.Add(newRow );
}
}

Related

GetChanges from merged datatables returns null

I have following code:
DataTable datTable3 = new DataTable();
datTable3 = datTable1.Clone();
datTable2.Merge(datTable1);
datTable3 = datTable2.GetChanges();
Want I want to do is: Compare DataTable1 with DataTable2 and when there are rows in DataTable1 which aren't in DataTable 2 then add these rows into a new DataTable(3). This code above gives me an empty DataTable3 each time although the rows in the first dt are not equal to the rows in my second dt. what am I doing wrong? Sorry if that question may be too easy but I'm using C# since a couple of months.
EDIT: I found this solution which doesn't work for me... Why?
DataTable datTable3 = new DataTable();
datTable3 = datTable1.Clone();
foreach (DataRow row in datTable1.Rows)
{
datTable3.ImportRow(row);
}
foreach (DataRow row in datTable3.Rows)
{
row.SetAdded();
}
datTable2.Merge(datTable3);
DataTable datTableFinal = datTable2.GetChanges(DataRowState.Added);
// shows me a datatable with again the values from datTable1
// even if they are already in datTable2!
datTable2.RejectChanges();
datTable1.RejectChanges();
The DataTable.GetChanges() method Gets a copy of the DataTable that contains all changes made to it since it was loaded or AcceptChanges was last called.
In other words, GetChanges() is dependent on the DataRow.RowState property. A DataTable.Merge() will either preserve their 'RowState' property, or reset it to 'Unchanged'.
This means that when you merge two DataTables with rows that have 'Unchanged' RowStates, the merged table will also contain 'Unchanged' rows and the DataTable.GetChanges method will return null or Nothing.
EDIT : You can always iterate through the DataTable to see what rows are added to the merged table. Something like
foreach(DataRow row in datTable2.Rows)
{
Console.WriteLine("--- Row ---"); // Print separator.
foreach (var item in row.ItemArray) // Loop over the items.
{
Console.Write("Item: "); // Print label.
Console.WriteLine(item); // Invokes ToString abstract method.
}
}
Iterate through and use LoadDataRow(object[] value, bool fAcceptChanges) :
foreach (DataRow row in MergeTable.Rows)
{
TargetTable.LoadDataRow(row.ItemArray, false);
}
var changes = TargetTable.GetChanges();
changes had the desired value when I tried this method.

Check if row exists in DataTable?

I have a datatable and a row. I want to import the row to the datatable only if it does not exist in the datatable.
How can i do that?
If you use a typed DataSet, I.e. declared in design time, the "linq Contains method" takes a typed DataRow. The default IEqualityComparer will compare all values in the DataRow. (Which is normally useless, since you should have a key defined).
DataSet1 ds = new DataSet1();
DataSet1.DataTable1Row row = ds.DataTable1.AddDataTable1Row(bla, bla);
bool exists = ds.DataTable1.Contains(row);
You can use LINQ to check if row is present in datatable. Follow this solution, and replace "id" with your row's primary key, by which you can uniquely identify a row in a table.
DataRow dr = null; // assign your DR here
DataTable dt = new DataTable(); // assign Datatable instance here.
var k = (from r in dt.Rows.OfType<DataRow>() where r["id"].ToString() == dr["id"].ToString() select r).FirstOrDefault();
if(k != null)
{ // Row is present }
if you want to check all the cells in a DataRow, you can try this function:
bool ContainDataRowInDataTable(DataTable T,DataRow R)
{
foreach (DataRow item in T.Rows)
{
if (Enumerable.SequenceEqual(item.ItemArray, R.ItemArray))
return true;
}
return false;
}
you can use Contains as below
if(DataTable.Columns.Contains("RowName"))
{
//Do some stuffs here
}
Tried all answers here but did not work, so I made something for myself which works in my case. The code is pretty simple, it checks if the row you want to add already exists in the datatable - if it does not exist in the datatable, add it.
// fill dt with information
DataTable dt = new DataTable();
// create a new row and fill it with information
DataRow dr = dt.NewRow();
// distinct
bool isDistinct = true;
for (int i=0; i < dt.Rows.Count; i++)
{
// check if both rows are equal
if (Enumerable.SequenceEqual(dt.Rows[i].ItemArray, dr.ItemArray))
{
// it already exists
isDistinct = false;
break;
}
}
if (isDistinct)
{
dt.Rows.Add(dr);
}
if ( Datatable1.Rows[NumOfRow].ToString().Deleted == "Deleted")
You should check row existence by comparing primary keys:
static bool RowExists(DataTable table, DataRow row)
{
var pk = table.PrimaryKey
.Select(column => row[column, DataRowVersion.Original])
.ToArray();
return table.Rows.Contains(pk);
}
Reason is, DataRow that you are trying to check against existing DataTable is, in real-life scenarios, different class instance compared to the DataRaw in the table, even when same DataRaw already exists in the DataTable. Usual .NET equality-comparison does not work properly in this scenarios. That includes DataTable.Contains(...) method.
To properly check for DataRaw existence in the table, primary key given DataRaw should be searched for in the table.
You can check using any with the key value
If (value.Tables(0).AsEnumerable().Any(Function(x) key = x.Field(Of Integer)("ProductId") ))

ImportRow make the new row column missing

I want to copy all rows in old datatable (oldDT) to a new datatable (dt) using ImportRow method. But the new row doesn't have a same column with the old one. Here is my code:
foreach (DataRow dr in oldDT.Rows)
{
MessageBox.Show(dr["tenant_no"].ToString()); //giving a correct result
dt.ImportRow(dr);
MessageBox.Show(dt.Rows[0]["tenant_no"].ToString()); //giving an error Column 'tenant_no' does not belong to table .
}
i try to use the answer C# simple way to copy or clone a DataRow? and here is my new code:
foreach (DataRow dr in oldDT.Rows)
{
MessageBox.Show(dr["tenant_no"].ToString());
DataRow newDR = oldDT.NewRow();
newDR.ItemArray = dr.ItemArray.Clone() as object[];
dt.Rows.Add(newDR); //giving an error "This row already belongs to another table."
MessageBox.Show(dt.Rows[0]["tenant_no"].ToString());
}
Anyone can help me?
Try this... this will work
DataTable dt= new DataTable();
dt= oldDT.Clone();
for (int i=0;i < oldDT.Rows.Count; i++)
{
dt.ImportRow(dataTable.Rows[i]);
}
You could use DataTable.Copy, if you are not locked into using the ImportRow :
Copies both the structure and data for this DataTable.
DataTable dt = oldDt.Copy();

Avoid a column when checking DataRowState for a DataRow

Is there any way in C# to check if the datatable values are changed or not from the time it is loaded from DB ? But I know we can check the DataRowState to identify it. But here I want to avoid or neglect a particular column when checking the DataRowState for a DataRow. Simple code is shown here.
foreach (DataRow dr in DataTable.Rows)
{
if (dr.RowState != DataRowState.Unchanged)
{
// code
}
}
When checking the DataRowState for a DataRow, how can i neglect or avoid a column and check all the values of the other columns in the DataRow ?
Something like as shown below :
// avoid Status column value and consider all other column values in the row.
foreach (DataRow dr in DataTable.Rows.Where(not Status column))
{
if (dr.RowState != DataRowState.Unchanged)
{
// code
}
}
You can get all record that chenged with this code:
DataSet changedRecords = dataSet1.GetChanges();

C# datatable, duplicate data

For testing I would like to expand my result set. I have a DataTable dt that has 7 or so results. I would like to do something like:
dt.Rows.Add(dt); a few times, just to make the data set larger.
I also tried dt.Rows.Add(dt.Rows[0]);
The first gave an error about the type, the second said the row already existed.
You need to do something like what's below. Basically generate a new row using the values from the existing row.
DataTable dt = new DataTable();
DataRow dr = dt.Rows[0];
dt.Rows.Add(dr.ItemArray);
You need to copy values to new row:
DataRow row = dt.NewRow();
row.ItemArray = dt.Rows[0].ItemArray;
dt.Rows.Add(row);
The first item fails because the function expects a DataRow param.
The second item fails, because you are trying to add an item from the table, so it will inherently exist.
Try:
DataTable dt;
DataRow dr = dt.NewRow();
dr["field"] = "Some Value";
dt.Rows.Add(dr);
Check out the DataRow Class article on MSDN

Categories

Resources