Consulta LINQ en una DataTable

Intento realizar una consulta LINQ en un objeto DataTable y, curiosamente, me parece 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 esta permitido. ¿Cómo puedo hacer que algo como esto funcione?

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

No puede realizar consultas en la colección Filas de DataTable , ya que DataRowCollection no implementa IEnumerable . AsEnumerable() usar la extensión AsEnumerable() para DataTable . Al igual que:

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

Y como dice Keith, necesitarás agregar una referencia a System.Data.DataSetExtensions

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

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

No es que no se les permitiera deliberadamente en DataTables, es solo que DataTables es anterior a las construcciones IQueryable y genéricas de IEnumerable en las que se pueden realizar consultas de Linq.

Ambas interfaces requieren algún tipo de validación de seguridad de tipo. Los DataTables no están fuertemente tipados. Esta es la misma razón por la cual las personas no pueden consultar contra una ArrayList, por ejemplo.

Para que Linq funcione, debe asignar sus resultados a objetos de tipo seguro y consultar en su lugar.

Como dijo @ ch00k:

 using System.Data; //needed for the extension methods to work ... var results = from myRow in myDataTable.Rows where myRow.Field("RowNo") == 1 select myRow; //select the thing you want, not the collection 

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

 var query = from p in dt.AsEnumerable() where p.Field("code") == this.txtCat.Text select new { name = p.Field("name"), age= p.Field("age") }; 

Usar LINQ para manipular datos en DataSet / DataTable

 var results = from myRow in tblCurrentStock.AsEnumerable() where myRow.Field("item_name").ToUpper().StartsWith(tbSearchItem.Text.ToUpper()) select myRow; DataView view = results.AsDataView(); 
 //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 ie AsEnumerable() this will return EnumerableRowCollection // Now Query DataTable to find Row whoes ID=1 DataRow drow = dt.AsEnumerable().Where(p=>p.Field(0)==1).FirstOrDefault(); // 

Me doy cuenta de que esto ha sido respondido varias veces, pero para ofrecer otro enfoque, me gusta usar el .Cast() , me ayuda a mantener la cordura al ver el tipo explícito definido, y en el fondo, creo .AsEnumerable() llama de todos modos:

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

o

 var results = myDataTable.Rows.Cast() .FirstOrDefault(x => x.Field("RowNo") == 1); 

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

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

Pruebe esta simple línea de consulta:

 var result=myDataTable.AsEnumerable().Where(myRow => myRow.Field("RowNo") == 1); 

Prueba esto

 var row = (from result in dt.AsEnumerable().OrderBy( result => Guid.NewGuid()) select result).Take(3) ; 

Esta es una forma simple que funciona para mí y usa 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() 

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

Ex. Nombre de clase de DataSet-> CustomSet, nombre de clase DataRow-> CustomTableRow (con columnas definidas: RowNo, …)

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

O (como prefiero)

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

En mi aplicación encontré que el uso de 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 la biblioteca Json.Net de James Newtonking ( 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 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(jsonResults); 
 IEnumerable result = from myRow in dataTableResult.AsEnumerable() select myRow["server"].ToString() ; 

Puedes hacer que funcione elegantemente a través de linq así:

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

O como dynamic linq this (AsDynamic se llama directamente en DataSet):

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

Prefiero el último enfoque mientras que es el más flexible. PD: No te olvides de conectar la referencia de System.Data.DataSetExtensions.dll

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

 Dim results = From myRow In myDataTable Where myRow.Field(Of Int32)("RowNo") = 1 Select myRow 

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

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( dt.Columns[1] ); foreach( var name in names ) { Console.WriteLine( name ); } 

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

 List result = myDataTable.AsEnumerable().Select(x=> new MyClass(){ Property1 = (string)x.Field("ColumnName1"), Property1 = (int)x.Field("ColumnName2"), Property1 = (bool)x.Field("ColumnName3"), });