Linq to check if the datarow exists in a datatable - c#

I have my query as below
DataRow dr = objDtModifier.Rows[num];
var existingRows = resultDataTable.AsEnumerable().Where(row => row == dr);
But existingRows.Count always returns me zero .
Can anyone tell what's wrong here .

You are comparing a row object from the objDtModifier source colloction with a different set of row objects in a resultDataTable collection which will alway return an empty result set as they are a different set of object references (this is regardless of whether they contain the same data or not).
Is there a property you can test against? eg:
var existingRows = resultDataTable.AsEnumerable().Where(row => row.Id == dr.Id);

It happens because row and dr not same object and your are going to compare two object,
try to check columns of row , something like primary keyvalue

You compare a row object which you get from a table called objDtModifier against a row from a table called resultDataTable. So unless that's a typo this is probably what's wrong.
Edit: Even if they contain rows from the same database table you are comparing the object references of two different row objects - this will fail. You need to compare two columns which uniquely identify the row (or maybe a set of columns).

No matter if they are same type. If objDtModifier and resultDataTable does not contain same instances the behaviour you get is correct.
row==dr uses equality by reference, like chris stated. if objDtModifier and resultDataTable contains diffrent row instances but refers to same data, you might want to use row.id==dr.id if id is the primary key of the datable.

Related

Get updated row in ASPxGridView.RowUpdating event with composite KeyFieldName

I'm trying to create a custom edit script for my ASPxGridView. I have a second grid in which I used the code below to obtain the row that has been updated. This, however, doesn't work because my grid has a composite KeyFieldName (because the table it's based on has a primary key made up of two columns). This results in the FindVisibleIndexByKeyValue method always returning -1.
Any ideas on how I could obtain the row some other way?
object key = e.Keys[grid.KeyFieldName];
int row = grid.FindVisibleIndexByKeyValue(key);
Edit: The problem actually is that e.Keys[grid.KeyFieldName] returns null.
This can be accomplished by saving the keys into an array of objects one by one and passing that array to FindVisibleIndexByKeyValue().
object[] key = new object[2];
key[0]= e.Keys["firstKey"];
key[1] = e.Keys["secondKey"];
int row = grid.FindVisibleIndexByKeyValue(key);

How do I populate a DataRow and assign it to one of two tables based on a condition?

I have data being processed by an app which needs to sort the data based on whether or not a bit is flipped. The tables are identical. The code as it stands looks something like this:
DataTable dt2 = dt1.Clone();
DataRow r = dt1.NewRow();
FillUp(ref r);
if(bitISetEarlier)
dt2.ImportRow(r);
else
dt1.ImportRow(r);
Now, a clear problem I was having is that if the row wasn't already attached to a table, ImportRow() fails silently and I end up with an empty table. When I changed this to:
if(bitISetEarlier)
dt2.Rows.Add(r);
else
dt1.Rows.Add(r);
I started getting an exception saying that a function was trying to add a row that existed for another table. So when I tried this:
if(bitISetEarlier)
if(r.RowState == DataRowState.Detached)
dt2.Rows.Add(r)
else dt2.ImportRow(r);
else
if(r.RowState == DataRowState.Detached)
dt1.Rows.Add(r)
else dt1.ImportRow(r);
the exception stopped, but any attempt to assign to dt2 still states that the row belongs to another table, but if I comment out the dt2 if statement and just attempt ImportRow(), the dt2.Rows.Count remains at 0 and no records assigned.
I need to populate the DataRow before knowing which table it belongs in, but I have no idea what columns the row will have before it hits this function. The condition that indicates which table it should go to is not stored with the data in the DataTable.
Is the problem that even though they have identical columns, NewRow() is adding an attribute to the row that makes it incompatible with the sister table? Is there a way I can get the same functionality as NewRow() (copy schema without knowing what any of the columns are ahead of time) but that I can dynamically assign? I'm aware I could probably manually construct a row that is compatible with either by wrapping it in a for loop and building out the columns every time i need the new row using the DataTable.Columns property, but I'd like to avoid doing that if possible.
I found my solution. Since I can't add the row built off of one table to the other table directly, I figured it was the DataRow object that was problematic, but the ItemArray property was probably all I needed.
if (isErrorRow)
{
//nr is the NewRow for dt1
var nr2 = dt2.NewRow();
nr2.ItemArray = nr.ItemArray;
dt2.Rows.Add(nr2);
}
This effectively cloned the rows.

How to avoid adding duplicate rows to a datatable

I'm using a SqlDataReader to add row by row into a datatable like follows:
while (reader.Read())
{
dataTable.LoadDataRow(reader.CurrentRow(), LoadOption.PreserveChanges);
}
This works, but I need to be able to avoid adding duplicate rows to the dataTable. I would love to be able to use the Contains or Find methods from the dataTable, but I can't find a way to turn the object[] from reader.CurrentRow() into a DataRow to compare to without adding it to a datatable.
I've looked into the option of making a hashset of the object[]s, and then adding them all at once to the datatable at the end, but I forgot that the default object IEqualityComparer only compares the reference.
Is there a feasible way of doing this without removing the duplicates at the end?
If removing the duplicates is the only way to go, what is the best way to do that?
EDIT:
I'm splitting distinct rows from the database into separate datatables in code. Each row from the query result is distinct, but sections of each row are not. Unfortunately I need to do exactly what my question is asking, as the results from the query are already distinct.
You didn't provide a ton of detail, but I hope this is comprehensive.
If you need a single column to be unique, then in your Columns collection in your datatable, specify the column like this:
DataTable appeals = new DataTable("Appeals");
appeals.Columns["PriorAppealNumber"].Unique = true;
DataColumn keyField = new DataColumn("AppealNumber", typeof(string));
appeals.Columns.Add(keyField);
If the uniqueness needs to span multiple rows, this is the method:
var myUniqueConstraint = new UniqueConstraint( new DataColumn[] {appeals.Columns[0], appeals.Columns[1], appeals.Columns[2]} );
appeals.Constraints.Add(myUniqueConstraint);
That will enforce the constraints BEFORE you try to commit back to the source database.
The easiest way is to actually make sure there are no duplicate rows at all - if you're querying relational database use DISTINCT - that will return only unique rows.

DataRow.RowError is not getting copied when using DataTable.Load

I have to copy rows from one table to another. In the source table I can have RowError set on rows.
When I do this:
targetTable.BeginLoadData();
targetTable.Load( new DataTableReader( sourceTable ) )
targetTable.EndLoadData();
The target table does not get row errors copied on its rows from source table.
Can anyone tell what am I supposed to do to make it work?
Thanks.
EDIT: I do not want to lose the data already present in the target table. Nor do I want to change the reference.
Try this:
targetTable = sourceTable.Copy();
Creating a reader won't give you the expected result in this case, because its (reader) goal will be extracting the value of each row, not the appendant properties.
Update:
In this case, you should:
foreach (DataRow drImport in sourceTable.Rows) {
targetTable.ImportRow(drImport);
}
Sorry, just before posting I've seen your other observation about the reference. I'm afraid you can't have the same row (same reference) assigned to two ore more tables. See this.

Can I access entire DataTable if all I have is a single DataRow?

DataRow contains a Table property, which seems to return the entire Table for which this row belongs.
I'd like to know if I can use that table safely, or if there are gotcha's.
In http://msdn.microsoft.com/en-us/library/system.data.datarow.table.aspx documentation, it says "A DataRow does not necessarily belong to any table's collection of rows. This behavior occurs when the DataRow has been created but not added to the DataRowCollection.", but I know for a fact my row belongs to a table.
In terms of pointers, if each Row from DataTable points to original DataTable, than I'm good to go. Is that all 'Table' property does?
Just to explain why I'm trying to get entire Table based on a single DataRow:
I'm using linq to join two (sometimes more) tables. I'd like to have a generic routine which takes the output of linq (var), and generate a single DataTable with all results.
I had opened another question at stackoverflow (Join in LINQ that avoids explicitly naming properties in "new {}"?), but so far there doesn't seem to be a generic solution, so I'm trying to write one.
if you know the row is part of table than yes you can access it without any problem. if the possibility exists where the row may not be associated to a table than check if the property is null.
if(row.Table == null)
{
}
else
{
}
As long as it's not null, you can use it freely.

Categories

Resources