Consulta LINQ sobre una DataTable


Estoy tratando de realizar una consulta LINQ en un objeto DataTable y curiosamente estoy encontrando que realizar tales consultas en DataTables no es sencillo. Por ejemplo:

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

Esto no está permitido. ¿Cómo hago que funcione algo como esto?

¡Me sorprende que las consultas LINQ no estén permitidas en las tablas de datos!

Author: Peter Mortensen, 2008-08-14

21 answers

No puede consultar la colección DataTable's Rows, ya que DataRowCollection no implementa IEnumerable<T>. Necesita usar la extensión AsEnumerable() para DataTable. Así:

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

Y como dice Keith, necesitarás agregar una referencia al Sistema .Datos.Extensiones del conjunto de datos

AsEnumerable() devuelve IEnumerable<DataRow>. Si necesita convertir IEnumerable<DataRow> a DataTable, use la extensión CopyToDataTable().

 1141
Author: Collin K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-02 16:45:09
var results = from DataRow myRow in myDataTable.Rows
    where (int)myRow["RowNo"] == 1
    select myRow
 115
Author: JoelFan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-05 02:53:10

No es que no se hayan permitido deliberadamente en las tablas de datos, es solo que las tablas de datos son anteriores a las construcciones IQueryable y genéricaerableumerable en las que se pueden realizar consultas Linq.

Ambas interfaces requieren algún tipo de validación de seguridad. Las tablas de datos no están fuertemente escritas. Esta es la misma razón por la que las personas no pueden consultar contra una ArrayList, por ejemplo.

Para que Linq funcione, debe mapear sus resultados con objetos seguros de tipo y consultar con eso en su lugar.

 58
Author: Jon Limjap,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-14 10:10:55

Como @ch00k dijo:

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

También necesita agregar una referencia de proyecto a System.Data.DataSetExtensions

 46
Author: Keith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-14 11:07:52
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")                         
                    };
 35
Author: Ravi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-08 22:23:46

Uso de LINQ para manipular datos en 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();
 25
Author: Salim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-11 04:10:38
//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();
 // 
 24
Author: sushil pandey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-04 22:08:01

Me doy cuenta de que esto ha sido respondido varias veces, pero solo para ofrecer otro enfoque, me gusta usar el método .Cast<T>(), me ayuda a mantener la cordura al ver el tipo explícito definido, y en el fondo creo que .AsEnumerable() lo llama de todas formas:

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

O

var results = myDataTable.Rows.Cast<DataRow>()
                  .FirstOrDefault(x => x.Field<int>("RowNo") == 1);
 20
Author: vandsh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-18 02:07:52

Puede usar LINQ para objetos en la colección Rows, como así:

var results = from myRow in myDataTable.Rows where myRow.Field("RowNo") == 1 select myRow;
 13
Author: David Wengier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-14 10:11:08

Pruebe esta simple línea de consulta:

var result=myDataTable.AsEnumerable().Where(myRow => myRow.Field<int>("RowNo") == 1);
 13
Author: Mohit Verma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-15 12:15:34

Prueba esto

var row = (from result in dt.AsEnumerable().OrderBy( result => Guid.NewGuid()) select result).Take(3) ; 
 9
Author: midhun sankar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-18 07:51:09

Esta es una forma simple que funciona para mí y utiliza expresiones lambda:

var results = myDataTable.Select("").FirstOrDefault(x => (int)x["RowNo"] == 1)

Entonces si quieres un valor particular:

if(results != null) 
    var foo = results["ColName"].ToString()
 8
Author: Matt Kemp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-18 22:13:55

Lo más probable es que las clases para el DataSet, DataTable y DataRow ya estén definidas en la solución. Si ese es el caso, no necesitará la referencia DataSetExtensions.

Ex. DataSet class name - > CustomSet, DataRow class name - > CustomTableRow (con columnas definidas: RowNo, ...)

var result = from myRow in myDataTable.Rows.OfType<CustomSet.CustomTableRow>()
             where myRow.RowNo == 1
             select myRow;

O (como yo prefiero)

var result = myDataTable.Rows.OfType<CustomSet.CustomTableRow>().Where(myRow => myRow.RowNo);
 8
Author: xadriel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-15 12:16:07
var results = from myRow in myDataTable
where results.Field<Int32>("RowNo") == 1
select results;
 7
Author: Vinay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-01 12:16:51

En mi aplicación descubrí que usar LINQ para Conjuntos de datos con la extensión AsEnumerable() para DataTable como se sugiere en la respuesta fue extremadamente lento. Si está interesado en optimizar la velocidad, use el programa de James Newtonking Json.Net biblioteca ( http://james.newtonking.com/json/help/index.html )

// Serialize the DataTable to a json string
string serializedTable = JsonConvert.SerializeObject(myDataTable);    
Jarray dataRows = Jarray.Parse(serializedTable);

// Run the LINQ query
List<JToken> results = (from row in dataRows
                    where (int) row["ans_key"] == 42
                    select row).ToList();

// If you need the results to be in a DataTable
string jsonResults = JsonConvert.SerializeObject(results);
DataTable resultsTable = JsonConvert.DeserializeObject<DataTable>(jsonResults);
 4
Author: LandedGently,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-14 17:51:10
IEnumerable<string> result = from myRow in dataTableResult.AsEnumerable()
                             select myRow["server"].ToString() ;
 4
Author: Iman Abidi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-04 07:32:55

Puedes conseguir que funcione elegante a través de linq así:

from prod in TenMostExpensiveProducts().Tables[0].AsEnumerable()
where prod.Field<decimal>("UnitPrice") > 62.500M
select prod

O como dynamic linq esto (AsDynamic se llama directamente en el conjunto de datos):

TenMostExpensiveProducts().AsDynamic().Where (x => x.UnitPrice > 62.500M)

Prefiero el último enfoque mientras que es es el más flexible. P.d.: No olvides conectar System.Data.DataSetExtensions.dll referencia

 3
Author: AuthorProxy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-06 09:44:54

Para VB.NET El código se verá así:

Dim results = From myRow In myDataTable  
Where myRow.Field(Of Int32)("RowNo") = 1 Select myRow
 3
Author: Abdul Saboor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-11 04:07:40

Ejemplo sobre cómo lograr esto se proporciona a continuación:

DataSet dataSet = new DataSet(); //Create a dataset
dataSet = _DataEntryDataLayer.ReadResults(); //Call to the dataLayer to return the data

//LINQ query on a DataTable
var dataList = dataSet.Tables["DataTable"]
              .AsEnumerable()
              .Select(i => new
              {
                 ID = i["ID"],
                 Name = i["Name"]
               }).ToList();
 3
Author: Ryan Gavin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-25 16:04:52

Prueba esto...

SqlCommand cmd = new SqlCommand( "Select * from Employee",con);
SqlDataReader dr = cmd.ExecuteReader( );
DataTable dt = new DataTable( "Employee" );
dt.Load( dr );
var Data = dt.AsEnumerable( );
var names = from emp in Data select emp.Field<String>( dt.Columns[1] );
foreach( var name in names )
{
    Console.WriteLine( name );
}
 2
Author: Uthaiah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-20 14:17:10

Puede probar esto, pero debe estar seguro del tipo de valores para cada columna

List<MyClass> result = myDataTable.AsEnumerable().Select(x=> new MyClass(){
     Property1 = (string)x.Field<string>("ColumnName1"),
     Property2 = (int)x.Field<int>("ColumnName2"),
     Property3 = (bool)x.Field<bool>("ColumnName3"),    
});
 2
Author: Gabriel Martinez Bustos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-25 14:33:48