2011-01-10 4 views
0

У меня есть таблица данных, и я хочу выбрать все различные имена из результата. Я написал для него следующий запрос linq.C# linq question

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

Теперь, как я могу перебирать отдельные столбцы? Похоже, я не могу сделать foreach(DataRow Row in distinctRows), Он дает мне «Невозможно преобразовать тип« Анонимный тип №1 »в« Ошибка System.Data.DataRow »»

+4

Вы прочитали ошибку? – SLaks

+4

В будущем вы, вероятно, получите лучшие результаты, если заголовок вопроса описывает ваш вопрос. «Вопрос C# linq» ничего нам не говорит; C# и linq уже являются тегами, и мы знаем его вопрос. –

+0

@ Эрик, спасибо, что указали это. Извините за использование глупого названия :) – imak

ответ

3

Поскольку вы выбираете только одно поле, здесь вам не нужен анонимный тип. Просто выберите имена, а затем перейдите по отдельным. К оглавлению:

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

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

Обратите внимание, что ошибка дает понять, в чем проблема. Вы пытаетесь преобразовать экземпляр анонимного типа в экземпляр DataRow, и это невозможно. Без изменения кода, вы можете перебирать это как

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

Но я хотел бы изменить это в соответствии с выше, как вам не нужен анонимный тип и ваши имена переменных и имена полей являются бедными.

+0

Это 'объект'. – SLaks

2

Это не DataRows; это анонимные объекты.
Чтобы пройти через них, вам нужно объявить переменную, используя ключевое слово var.

Однако в анонимном типе нет никакого смысла.
Вы можете изменить ваш запрос на select myDataRow.Field<string>("Name"), чтобы получить набор строк.

+0

вы можете привести пример – imak

+1

Зачем вам пример? Если вы действительно прочитали ошибку, решение должно быть очевидно. – SLaks

0

Это потому, что myDataRow["Name"] не возвращает DataRow. Попробуйте

foreach(var item in distinctRows) {} 
1

Вы можете использовать ключевое слово var для обозначения анонимных типов (это то, что вы возвращаете IEnumerable<>).

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

Поскольку вы только возвращение анонимных типов с одной строкой собственности, однако, вы можете также проецировать IEnumerable<string>

0

Это потому, что возвращаемое значение не является DataRow. Это тип ad-hoc, который содержит свойство col1.

0

Чтобы построить на SLaks ответ. , ,

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 
} 
0

Проблема здесь состоит в том, что вы выбираете новый анонимный тип, делая select new { col1 = myDataRow ["Name"]} и не самой фактической строки. Поэтому, когда вы пытаетесь повторить это как DataRow, он будет выходить из строя, потому что выбран ваш анонимный тип не типа DataRow.

Если вы хотите, чтобы иметь возможность выбирать целую строку данных, а не только поле имени, вам необходимо реализовать пользовательский код IEqualityComparer для строки данных для перехода к методу расширения Distinct().

Примером может быть:

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(); 
    } 
} 

Затем, используя его:

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

Вы также можете Foreach их, но сначала нужно было перечислить их в следующем виде:

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

foreach(string str in rlst) 
{} 

Надеюсь, это помогло