LINQ-запрос к DataTable - PullRequest
       154

LINQ-запрос к DataTable

959 голосов
/ 14 августа 2008

Я пытаюсь выполнить запрос LINQ к объекту DataTable, и странным образом обнаруживаю, что выполнение таких запросов к объектам DataTable не является простым. Например:

var results = from myRow in myDataTable
where results.Field("RowNo") == 1
select results;

Это не разрешено. Как мне заставить что-то подобное работать?

Я поражен, что запросы LINQ не разрешены в DataTables!

Ответы [ 21 ]

1210 голосов
/ 14 августа 2008

Вы не можете выполнять запросы к коллекции DataTable Rows , поскольку DataRowCollection не реализует IEnumerable<T>. Вам нужно использовать расширение AsEnumerable() для DataTable. Вот так:

var results = from myRow in myDataTable.AsEnumerable()
where myRow.Field<int>("RowNo") == 1
select myRow;

И, как говорит Кит, вам нужно добавить ссылку на System.Data.DataSetExtensions

AsEnumerable() возвращает IEnumerable<DataRow>. Если вам нужно преобразовать IEnumerable<DataRow> в DataTable, используйте расширение CopyToDataTable().

Ниже приведен запрос с лямбда-выражением,

var result = myDataTable
    .AsEnumerable()
    .Where(myRow => myRow.Field<int>("RowNo") == 1);
123 голосов
/ 05 марта 2009
var results = from DataRow myRow in myDataTable.Rows
    where (int)myRow["RowNo"] == 1
    select myRow
66 голосов
/ 14 августа 2008

Дело не в том, что они были намеренно запрещены в DataTables, просто в DataTable предшествуют IQueryable и универсальные конструкции IEnumerable, для которых могут выполняться запросы Linq.

Оба интерфейса требуют некоторой проверки безопасности типов. DataTables не являются строго типизированными. Это та же самая причина, по которой люди не могут запрашивать ArrayList, например.

Чтобы Linq работал, вам нужно сопоставить свои результаты с объектно-безопасными объектами и вместо этого выполнить запрос.

48 голосов
/ 14 августа 2008

Как сказал @ ch00k:

using System.Data; //needed for the extension methods to work

...

var results = 
    from myRow in myDataTable.Rows 
    where myRow.Field<int>("RowNo") == 1 
    select myRow; //select the thing you want, not the collection

Вам также необходимо добавить ссылку на проект к System.Data.DataSetExtensions

38 голосов
/ 23 мая 2010
var query = from p in dt.AsEnumerable()
                    where p.Field<string>("code") == this.txtCat.Text
                    select new
                    {
                        name = p.Field<string>("name"),
                        age= p.Field<int>("age")                         
                    };
28 голосов
/ 05 января 2012
//Create DataTable 
DataTable dt= new DataTable();
dt.Columns.AddRange(New DataColumn[]
{
   new DataColumn("ID",typeOf(System.Int32)),
   new DataColumn("Name",typeOf(System.String))

});

//Fill with data

dt.Rows.Add(new Object[]{1,"Test1"});
dt.Rows.Add(new Object[]{2,"Test2"});

//Now  Query DataTable with linq
//To work with linq it should required our source implement IEnumerable interface.
//But DataTable not Implement IEnumerable interface
//So we call DataTable Extension method  i.e AsEnumerable() this will return EnumerableRowCollection<DataRow>


// Now Query DataTable to find Row whoes ID=1

DataRow drow = dt.AsEnumerable().Where(p=>p.Field<Int32>(0)==1).FirstOrDefault();
 // 
28 голосов
/ 03 февраля 2016

Я понимаю, что на этот вопрос уже отвечали несколько раз, но просто для того, чтобы предложить другой подход, мне нравится использовать метод .Cast<T>(), он помогает мне сохранять здравый рассудок, видя определенный явный тип, и в глубине души я думаю .AsEnumerable() называет это в любом случае:

var results = from myRow in myDataTable.Rows.Cast<DataRow>()
                  where myRow.Field<int>("RowNo") == 1 select myRow;

или

var results = myDataTable.Rows.Cast<DataRow>()
                  .FirstOrDefault(x => x.Field<int>("RowNo") == 1);
27 голосов
/ 13 июля 2011

Использование LINQ для управления данными в DataSet / DataTable

var results = from myRow in tblCurrentStock.AsEnumerable()
              where myRow.Field<string>("item_name").ToUpper().StartsWith(tbSearchItem.Text.ToUpper())
              select myRow;
DataView view = results.AsDataView();
19 голосов
/ 05 апреля 2016

Попробуйте эту простую строку запроса:

var result=myDataTable.AsEnumerable().Where(myRow => myRow.Field<int>("RowNo") == 1);
15 голосов
/ 14 августа 2008

Вы можете использовать LINQ для объектов в коллекции Rows, например:

var results = from myRow in myDataTable.Rows where myRow.Field("RowNo") == 1 select myRow;
...