2009-08-12 12 views
6

Prima devo dire che sono un newby che utilizza LINQ. In realtà non l'ho mai usato prima, ma sto svolgendo un'attività in cui ho bisogno di filtrare un DataTable, utilizzando valori che verranno da una lista. Quindi mi piacerebbe sapere se è possibile in LINQ eseguire una query su un Datatable utilizzando i valori nell'elenco come valori filtro. Qualcuno può darmi qualche suggerimentoSelezionare le righe da un DataSet utilizzando LINQ, dove l'elenco di RowsID si trova in un elenco <T>

Grazie.

risposta

7

Il modo migliore per farlo dipende da cosa si intende fare con i risultati filtrati. Hai bisogno dei risultati come DataTable per ulteriori operazioni o stai collegando i risultati ai dati?

Prendiamo l'esempio di seguito, che restituisce un (associabile) enumeratore di corrispondenti DataRow

//create sample table with sample rows 
DataTable table = new DataTable(); 

table.Columns.Add("id", typeof(int)); 

for (int i = 1; i < 11; i++) 
{ 
    DataRow row = table.NewRow(); 
    row[0] = i; 
    table.Rows.Add(row); 
} 

//filter the table by id (in a list) 
List<int> rowIds = new List<int> { 1, 3, 6 }; 

IEnumerable<DataRow> matchingRows = from DataRow row in table.Rows 
        where rowIds.Contains((int)row[0]) 
        select row; 

Se avete bisogno di un DataTable è possibile importare le righe in un'altra tabella:

DataTable filteredTable = table.Clone(); 

foreach (DataRow filteredRow in matchingRows) 
{ 
    filteredTable.ImportRow(filteredRow); 
} 
+0

un modo per convertire in un DataTable è quello di utilizzare .CopyToDataTable(), in questo caso assicurarsi di controllare se matchingRows.Any() restituisce true prima di fare matchingRows.CopyToDataTable(). Ciò richiede System.Data.DataTableExtensions – Enrico

2

Io di solito dare me stesso metodi di estensione quando ho bisogno di trattare un oggetto pre-LINQ come un oggetto pronto per LINQ. Ad esempio, stai cercando di eseguire una query su una DataRowCollection (proprietà DataTable.Rows) che probabilmente non utilizzi per qualcosa di più di un elenco di DataRows. Creo un metodo di estensione che esegue questa trasformazione per te (DataRowCollection su List<DataRow>). Inoltre, di solito uso un metodo di estensione per ottenere valori in modo sicuro quando non mi interessa lanciare un'eccezione se per qualche motivo viene fornito un nome di chiave non valido per la colonna. Quindi, puoi creare un metodo di estensione che prende un elenco di valori come ID e un nome di campo che contiene l'id per restituire ciò che desideri. Quando tutto è detto e fatto, questo viene fatto con una riga di codice. Ecco la classe con tutti i tuoi metodi di estensione.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Data; 

namespace ConsoleApplication11 
{ 
    public static class SystemDataHelpers 
    { 
     public static List<DataRow> RowList(this DataTable table) 
     { 
      List<DataRow> list = new List<DataRow>(); 
      foreach (DataRow row in table.Rows) 
       list.Add(row); 
      return list; 
     } 

     public static object GetItem(this DataRow row, string field) 
     { 
      if (!row.Table.Columns.Contains(field)) 
       return null; 
      return row[field]; 
     } 

     public static List<DataRow> GetRows(this DataTable table, List<int> ids, string fieldName) 
     { 
      Func<DataRow, bool> filter = row => ids.Contains((int)row.GetItem(fieldName)); 
      return table.RowList().Where(filter).ToList(); 
     } 
    } 
} 

Poi, diversa impostazione delle variabili (che non avrebbe bisogno di fare ... si dispone già di loro), il vero lavoro è fatto con una sola riga di codice (EDIT: una sola chiamata di metodo):

 DataTable table = new DataTable(); 
     List<int> rowIds = new List<int> { 1, 2, 3, 4 }; 
     string idFieldName = "row_id"; 

     List<DataRow> selected = table.GetRows(rowIds, idFieldName); 
Problemi correlati