Question

J'essaie d'effectuer une requête LINQ sur un objet DataTable et, bizarrement, je trouve qu'effectuer de telles requêtes sur 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 puis-je faire fonctionner quelque chose comme ça ?

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

Était-ce utile?

La solution

Vous ne pouvez pas interroger le DataTablec'est Lignes collecte, puisque DataRowCollection ne met pas en œuvre IEnumerable<T>.Vous devez utiliser le AsEnumerable() prolongation pour DataTable.Ainsi:

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

Et comme le dit Keith, vous devrez ajouter une référence à System.Data.DataSetExtensions

AsEnumerable() Retour IEnumerable<DataRow>.Si vous devez convertir IEnumerable<DataRow> à un DataTable, Utilisez le CopyToDataTable() extension.

Vous trouverez ci-dessous une requête avec Lambda Expression,

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

Autres conseils

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

Ce n'est pas qu'ils n'ont pas été délibérément autorisés sur les DataTables, c'est simplement que les DataTables sont antérieurs aux constructions IQueryable et IEnumerable génériques sur lesquelles les requêtes Linq peuvent être effectuées.

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

Pour que Linq fonctionne, vous devez mapper vos résultats sur des objets de type sécurisé et interroger ceux-ci à la place.

Comme @ch00k l'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

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

Je me rends compte que cela a été répondu à plusieurs reprises, mais juste pour proposer une autre approche, j'aime utiliser le .Cast<T>() méthode, cela m'aide à rester raisonnable en voyant le type explicite défini, et au fond je pense .AsEnumerable() l'appelle quand même :

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

Utiliser LINQ pour manipuler des données dans 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();

Essayez cette simple ligne de requête :

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

Vous pouvez utiliser LINQ to objets sur la collection Rows, comme ceci :

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

Essaye ça

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

C'est une méthode simple qui fonctionne pour moi et qui 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()

Très probablement, les classes de DataSet, DataTable et DataRow sont déjà définies dans la solution.Si tel est le cas, vous n'aurez pas besoin de la référence DataSetExtensions.

Ex.Nom de la classe DataSet-> CustomSet, nom de la classe DataRow-> CustomTableRow (avec colonnes définies :LigneNon, ...)

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

Ou (comme je préfère)

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

Dans mon application, j'ai constaté que l'utilisation de LINQ to Datasets avec l'extension AsEnumerable() pour DataTable comme suggéré dans la réponse était extrêmement lente.Si vous souhaitez optimiser la vitesse, utilisez la bibliothèque 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<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);

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

Pour VB.NET, le code ressemblera à ceci :

Dim results = From myRow In myDataTable  
Where myRow.Field(Of Int32)("RowNo") = 1 Select myRow
IEnumerable<string> result = from myRow in dataTableResult.AsEnumerable()
                             select myRow["server"].ToString() ;

Essaye ça...

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

Vous pouvez le faire fonctionner de manière élégante via Linq comme ceci :

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

Ou comme Dynamic Linq ceci (AsDynamic est appelé directement sur DataSet) :

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

Je préfère la dernière approche alors qu’elle est la plus flexible.P.S. :N'oubliez pas de vous connecter System.Data.DataSetExtensions.dll référence

vous pouvez essayer ceci, 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"),    
});
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top