简体   繁体   中英

LINQ Select distinct on DataTable not working

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM