imak
imak

Reputation: 6699

c# linq question

I have a data table and I want to select all distinct names from the result. I wrote following linq query for it.

var distinctRows = (from DataRow myDataRow in myDataTable.Rows 
                    select new { col1 = myDataRow ["Name"]}).Distinct();

Now how can I iterate through distinctRows? Seems like I cannot do foreach(DataRow Row in distinctRows), It gives me "Cannot convert type 'AnonymousType#1' to 'System.Data.DataRow'" error

Upvotes: 0

Views: 539

Answers (8)

Rami Alshareef
Rami Alshareef

Reputation: 7140

You can also foreach them but first you had to List them as the following :

List<string> rslt =(from DataRow myDataRow in myDataTable.Rows 
                    select new { col1 = myDataRow ["Name"].ToString()}).Distinct().ToList();

foreach(string str in rlst)
{}

Hope this helped

Upvotes: 0

Joshua Rodgers
Joshua Rodgers

Reputation: 5404

The problem here is that you're selecting a new anonymous type by doing select new { col1 = myDataRow ["Name"]} and not the actual row itself. So when you try to iterate this as DataRow, it will error out because your anonymous type being selected is not of type DataRow.

If you want to be able to select a whole data row and not just the name field, you will need to implement a custom IEqualityComparer for data row to pass to the Distinct() extension method.

An example would be:

public class NameComparer : IEqualityComparer<DataRow>
{
    public bool Equals(DataRow left, DataRow right)
    {
        return left.Field<string>("Name").Equals(right.Field<string>("Name"));
    }

    public int GetHashCode(DataRow obj)
    {
        return obj.ToString().GetHashCode();
    }
}

Then using it:

var distinctRows = (from DataRow myDataRow in myDataTable.Rows 
                    select myDataRow).Distinct(new NameComparer());

Upvotes: 0

Robaticus
Robaticus

Reputation: 23157

To build on SLaks answer . . .

var distinctRows = (from DataRow myDataRow in myDataTable.Rows 
                    select new { col1 = myDataRow ["Name"]}).Distinct();

foreach(var row in distinctRows)
{
    System.Console.Writeline(row.col1);  //should work fine
}

Upvotes: 0

flq
flq

Reputation: 22849

That's because the return value isn't a DataRow. It's an ad-hoc type that containes the property col1.

Upvotes: 0

Russ Cam
Russ Cam

Reputation: 125488

You can use the keyword var to refer to anonymous types (which is what you're returning an IEnumerable<> of).

foreach(var row in distinctRows)
{
    // do something with each anonymous type instance
}

Since you're only returning anonymous types with one string property however, you may as well project an IEnumerable<string>

Upvotes: 1

jason
jason

Reputation: 241641

Since you're only selecting one field, you don't need an anonymous type here. Just select the names and then iterate over the distinct ones. To wit:

var distinctNames = (from DataRow myDataRow in myDataTable.Rows
                     select myDataRow.Field<string>("Name")
                    ).Distinct();

foreach(var name in distinctNames) {
    Console.WriteLine(name);
}

Note that the error makes it very clear what the problem is here. You are trying to convert an instance of an anonymous type to an instance of DataRow and that is impossible. Without changing your code, you could iterate this as

foreach(var item in distinctRows) {
    Console.WriteLine((string)item.col1);
}

But I would change this as per the above as you don't need the anonymous type and your variable names and field names are poor.

Upvotes: 3

Tomas Jansson
Tomas Jansson

Reputation: 23472

That's because myDataRow["Name"] doesn't return a DataRow. Try

foreach(var item in distinctRows) {}

Upvotes: 0

SLaks
SLaks

Reputation: 887453

Those aren't DataRows; they're anonymous objects.
To loop through them, you need to declare the variable using the var keyword.

However, there's no point in the anonymous type in the first place.
You can change your query to select myDataRow.Field<string>("Name") to get a set of strings.

Upvotes: 2

Related Questions