LINQ query on a DataTable


I'm trying to perform a LINQ query on a DataTable object and bizarrely I am finding that performing such queries on DataTables is not straightforward. For example:

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

This is not allowed. How do I get something like this working?

I'm amazed that LINQ queries are not allowed on DataTables!

7/4/2014 8:44:08 PM

Accepted Answer

You can't query against the DataTable's Rows collection, since DataRowCollection doesn't implement IEnumerable<T>. You need to use the AsEnumerable() extension for DataTable. Like so:

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

And as @Keith says, you'll need to add a reference to System.Data.DataSetExtensions

AsEnumerable() returns IEnumerable<DataRow>. If you need to convert IEnumerable<DataRow> to a DataTable, use the CopyToDataTable() extension.

Below is query with Lambda Expression,

var result = myDataTable
    .Where(myRow => myRow.Field<int>("RowNo") == 1);
4/6/2020 9:22:00 AM

var results = from DataRow myRow in myDataTable.Rows
    where (int)myRow["RowNo"] == 1
    select myRow

It's not that they were deliberately not allowed on DataTables, it's just that DataTables pre-date the IQueryable and generic IEnumerable constructs on which Linq queries can be performed.

Both interfaces require some sort type-safety validation. DataTables are not strongly typed. This is the same reason why people can't query against an ArrayList, for example.

For Linq to work you need to map your results against type-safe objects and query against that instead.


As @ch00k said:

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

You also need to add a project reference to System.Data.DataSetExtensions


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")                         

the name and age fields are now part of the query object and can be accessed like so: Console.WriteLine(;


I realize this has been answered a few times over, but just to offer another approach:

I like to use the .Cast<T>() method, it helps me maintain sanity in seeing the explicit type defined and deep down I think .AsEnumerable() calls it anyways:

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

As noted in comments, no other assemblies needed as it's part of Linq (Reference)


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Email: [email protected]