Frage

Ich versuche, führen Sie eine LINQ-Abfrage für ein DataTable-Objekt und Bizarr ich finde, dass die Durchführung solcher Abfragen auf DataTables ist nicht einfach.Zum Beispiel:

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

Dies ist nicht erlaubt.Wie bekomme ich so etwas wie diese funktioniert?

Ich bin erstaunt, dass LINQ-Abfragen sind nicht gestattet DataTables!

War es hilfreich?

Lösung

Sie können nicht Abfrage der DataTable's Zeilen die Sammlung, seit DataRowCollection nicht implementiert IEnumerable<T>.Sie müssen verwenden AsEnumerable() Erweiterung für DataTable.Wie so:

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

Und wie Keith sagt, müssen Sie einen Verweis hinzufügen System.Daten.DataSetExtensions

AsEnumerable() zurück IEnumerable<DataRow>.Wenn Sie brauchen, um zu konvertieren IEnumerable<DataRow> zu einem DataTable, verwenden Sie die CopyToDataTable() Erweiterung.

Unten ist die Abfrage mit Lambda-Ausdruck,

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

Andere Tipps

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

Es ist nicht, dass Sie absichtlich nicht erlaubt DataTables, es ist nur so, dass DataTables pre-date the IQueryable und generische IEnumerable-Konstrukte auf, die Linq-Abfragen ausgeführt werden können.

Beide Schnittstellen benötigen irgendeine Art type-safety überprüfung.DataTables sind nicht stark typisiert.Dies ist der gleiche Grund, warum die Leute können nicht Abfrage gegen eine ArrayList, zum Beispiel.

Für Linq zu arbeiten, müssen Sie die Karte Ihrer Ergebnisse gegen Typ-sichere-Objekte und eine Abfrage auf, dass statt.

Wie @ch00k sagte:

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

Sie müssen auch fügen Sie einen Projektverweis auf 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")                         
                    };

Ich weiß, das beantwortet wurde ein paar mal vorbei, aber nur, um einen anderen Ansatz bietet, benutze ich gerne das .Cast<T>() Methode, die es mir hilft, halten Vernunft zu sehen, die explizite Typ definiert, und tief im Innern denke ich .AsEnumerable() nennt es sowieso:

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

oder

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

Verwenden von LINQ zum Bearbeiten von Daten in 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();

Versuchen Sie diese einfache Zeile der Abfrage:

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

Sie können die Verwendung von LINQ zu Objekten in der Rows-Auflistung, wie so:

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

Versuchen Sie, diese

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

Dies ist eine einfache Möglichkeit, die für mich funktioniert und verwendet lambda-Ausdrücke:

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

Dann, wenn Sie möchten einen bestimmten Wert:

if(results != null) 
    var foo = results["ColName"].ToString()

Die meisten wahrscheinlich, die Klassen für das DataSet, DataTable, and DataRow sind bereits in der Lösung.Wenn das der Fall ist, müssen Sie nicht die DataSetExtensions Referenz.

Ex.DataSet-Klasse-name-> CustomSet, DataRow-Klasse-name-> CustomTableRow (mit definierten Spalten:RowNo, ...)

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

Oder (wie ich es bevorzuge)

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;

In meiner Anwendung habe ich festgestellt, dass die Verwendung von LINQ für Datasets mit dem AsEnumerable () - Erweiterung für die DataTable-wie bereits in der Antwort war extrem langsam.Wenn Sie interessiert sind, die für die Geschwindigkeit zu optimieren, verwenden James Newtonking s Json.Net Bibliothek (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);

Beispiel, wie Sie diese erreichen Sie nachstehend:

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

Für VB.NET Der code wird wie folgt Aussehen:

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

Versuchen Sie diese...

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

Können Sie es bekommen arbeiten eleganten via linq wie diese:

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

Oder wie die dynamic linq-diese (AsDynamic direkt auf DataSet):

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

Ich bevorzuge die Letzte Ansatz zwar ist die flexibelste.P. S.:Vergessen Sie nicht, zu verbinden System.Data.DataSetExtensions.dll Referenz

Sie können versuchen, diese, aber Sie müssen sicher sein, die Art der Werte für jede Spalte

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"),    
});
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top