Requête LINQ sur un DataTable

j'essaie d'effectuer une requête LINQ sur un objet DataTable et bizarrement je trouve que l'exécution de telles requêtes sur des DataTables n'est pas simple. Par exemple:

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

ceci n'est pas autorisé. Comment je fais pour qu'un truc comme ça marche?

je suis étonné que les requêtes LINQ ne soient pas autorisées sur les DataTables!

904
demandé sur Peter Mortensen 2008-08-14 14:08:27

21 réponses

vous ne pouvez pas interroger contre le DataTable 's lignes collection, depuis DataRowCollection ne met pas en œuvre IEnumerable<T> . Vous devez utiliser l'extension AsEnumerable() pour DataTable . Comme ceci:

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

et comme Keith le dit, vous devrez ajouter une référence au système .Données.Extensions des données

AsEnumerable() renvoie IEnumerable<DataRow> . Si vous avez besoin de convertir IEnumerable<DataRow> en un DataTable , utilisez l'extension CopyToDataTable() .

1141
répondu Collin K 2012-03-02 16:45:09
var results = from DataRow myRow in myDataTable.Rows
    where (int)myRow["RowNo"] == 1
    select myRow
115
répondu JoelFan 2009-03-05 02:53:10

ce n'est pas qu'ils aient été délibérément interdits sur les DataTables, c'est juste que les DataTables datent d'avant les constructions IQueryable et générique IEnumerable sur lesquelles des requêtes Linq peuvent être effectuées.

les deux interfaces nécessitent une validation de type de sécurité. Les données ne sont pas fortement dactylographiées. C'est la même raison pour laquelle les gens ne peuvent pas interroger contre un ArrayList, par exemple.

pour que Linq fonctionne, vous devez cartographier vos résultats par type-safe les objets et les requêtes contre la place.

58
répondu Jon Limjap 2008-08-14 10:10:55

comme @ch00k a dit:

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

Vous devez également ajouter une référence de projet à System.Data.DataSetExtensions

46
répondu Keith 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
répondu Ravi 2011-02-08 22:23:46

utilisation de LINQ pour manipuler des données dans un ensemble de données / pouvant servir de données

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
répondu Salim 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
répondu sushil pandey 2015-11-04 22:08:01

je me rends compte que cela a été répondu plusieurs fois, mais juste pour offrir une autre approche, j'aime utiliser la méthode .Cast<T>() , il m'aide à maintenir la santé mentale en voyant le type explicite défini, et au fond je pense que .AsEnumerable() appelle de toute façon:

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

ou

var results = myDataTable.Rows.Cast<DataRow>()
                  .FirstOrDefault(x => x.Field<int>("RowNo") == 1);
20
répondu vandsh 2017-12-18 02:07:52

vous pouvez utiliser LINQ pour les objets de la collection Rows, comme suit:

var results = from myRow in myDataTable.Rows where myRow.Field("RowNo") == 1 select myRow;
13
répondu David Wengier 2008-08-14 10:11:08

essayez cette ligne simple de requête:

var result=myDataTable.AsEnumerable().Where(myRow => myRow.Field<int>("RowNo") == 1);
13
répondu Mohit Verma 2017-12-15 12:15:34

Essayez cette

var row = (from result in dt.AsEnumerable().OrderBy( result => Guid.NewGuid()) select result).Take(3) ; 
9
répondu midhun sankar 2012-05-18 07:51:09

C'est une manière simple qui fonctionne pour moi et utilise des expressions lambda:

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

alors si vous voulez une valeur particulière:

if(results != null) 
    var foo = results["ColName"].ToString()
8
répondu Matt Kemp 2015-03-18 22:13:55

très probablement, les classes pour L'ensemble de données, DataTable et DataRow sont déjà définies dans la solution. Si c'est le cas, vous n'aurez pas besoin de la référence data set extensions.

ex. Nom de la classe de l'ensemble de données - > CustomSet, nom de la classe de DataRow - > CustomTableRow (avec les colonnes définies: RowNo,...)

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

Ou (que je préfère)

var result = myDataTable.Rows.OfType<CustomSet.CustomTableRow>().Where(myRow => myRow.RowNo);
8
répondu xadriel 2017-12-15 12:16:07
var results = from myRow in myDataTable
where results.Field<Int32>("RowNo") == 1
select results;
7
répondu Vinay 2014-02-01 12:16:51

dans mon application, J'ai trouvé que L'utilisation de LINQ pour les ensembles de données avec l'extension AsEnumerable() pour datable comme suggéré dans la réponse était extrêmement lente. Si vous êtes intéressé par l'optimisation de la vitesse, utilisez celle de James Newtonking Json.Net bibliothèque ( ) 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
répondu LandedGently 2014-10-14 17:51:10
IEnumerable<string> result = from myRow in dataTableResult.AsEnumerable()
                             select myRow["server"].ToString() ;
4
répondu Iman Abidi 2015-08-04 07:32:55

vous pouvez obtenir un travail élégant via linq comme ceci:

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

ou comme linq dynamique cela (Asdynamique est appelé directement sur L'ensemble de données):

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

je préfère la dernière approche est la plus flexible. P. S.: N'oubliez pas de connecter System.Data.DataSetExtensions.dll référence

3
répondu AuthorProxy 2013-11-06 09:44:54

pour VB.NET le code ressemblera à ceci:

Dim results = From myRow In myDataTable  
Where myRow.Field(Of Int32)("RowNo") = 1 Select myRow
3
répondu Abdul Saboor 2014-02-11 04:07:40

exemple sur la façon d'y parvenir fourni ci-dessous:

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
répondu Ryan Gavin 2017-10-25 16:04:52

essayez ceci...

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
répondu Uthaiah 2017-04-20 14:17:10

vous pouvez essayer cela, mais vous devez être sûr du type de valeurs pour chaque colonne

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
répondu Gabriel Martinez Bustos 2018-09-25 14:33:48