I have the following datatable - Let's say called MyTable
:
Col1: Col2: Col3: Col4:
1 abc def <null>
2 abc def ghi
1 abc def <null>
3 abc def <null>
1 abc def <null>
And I'm trying to get the distinct rows:
Col1: Col2: Col3: Col4:
1 abc def <null>
2 abc def ghi
3 abc def <null>
I tried the following LINQ statement:
MyTable = (From dr As DataRow In MyTable Select dr).Distinct.CopyToDataTable
But it's returning the original datatable with the repeated rows back to me.
What am I doing wrong AND how can I get my desired output??
Distinct
relies on the objects all implementing IEquatable
and/or having sensible implementations of GetHashCode
and Equals
. The DataRow
class...doesn't. It doesn't check that the value of each column is equal in the Equals
method, it just uses the default implementation, which is to say that it checks that the references are equal, and that's not what you want.
You can provide your own IEqualityComparer
, since you can't change the methods in DataRow
.
The following should work, if you provide an instance of it to to Distinct
:
public class DataRowComparer : IEqualityComparer<DataRow>
{
public bool Equals(DataRow x, DataRow y)
{
for (int i = 0; i < x.Table.Columns.Count; i++)
{
if (!object.Equals(x[i], y[i]))
return false;
}
return true;
}
public int GetHashCode(DataRow obj)
{
unchecked
{
int output = 23;
for (int i = 0; i < obj.Table.Columns.Count; i++)
{
output += 19 * obj[i].GetHashCode();
}
return output;
}
}
}
Try like this;
var distinctRows = (from DataRow dRow in MyTable.Rows
select new {col1=dRow["Col1"],col2=dRow["Col2"], col3=dRow["Col3"], col4=dRow["Col4"]}).Distinct();
foreach (var row in distinctRows)
{
//
}
The problem is that every DataRow
in your DataTable
is a different object. Each is an instance.
Although @Servy's question truly was the correct way to do this - Thank you so much Servy! I also found another solution that at least seemed cleaner:
MyTable = MyTable.DefaultView.ToTable(True)
This allows you to ask for only distinct records, but negates by original request of doing it via LINQ - Figured I'd add it in for anyone else looking at this question in the future.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.