2009-08-12 14 views
6

Po pierwsze muszę powiedzieć, że jestem newby przy użyciu LINQ. Właściwie nigdy wcześniej nie użyłem, ale mam zadanie, w którym muszę filtrować DataTable, używając wartości, które będą pochodzić z listy. Chciałbym więc wiedzieć, czy w LINQ można zapytać o dane, używając wartości z listy jako wartości filtru. Ktoś może mi dać podpowiedź:Wybierz wiersze z DataSet za pomocą LINQ, gdzie lista RowsID są na liście <T>

Dziękuję.

Odpowiedz

7

Najlepszy sposób na zrobienie tego zależy od tego, co planujesz zrobić z filtrowanymi wynikami. Czy potrzebujesz wyników z powrotem jako DataTable do dalszych operacji, lub czy łączysz się z wynikami?

Take poniższy przykład, który zwraca (Bindable) wyliczający pasujących wierszy DataRows

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

Jeśli potrzebujesz DataTable można importować wierszy w innej tabeli:

DataTable filteredTable = table.Clone(); 

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

Jednym sposobem konwersji do DataTable jest za pomocą .CopyToDataTable(), w tym przypadku upewnij się, aby sprawdzić, czy matchingRows.Any() zwraca true przed wykonaniem matchingRows.CopyToDataTable(). Wymaga to System.Data.DataTableExtensions – Enrico

2

I zwykle dają sam metody rozszerzenia, gdy muszę traktować obiekt przed LINQ jako obiekt gotowy LINQ. Na przykład, szukasz kwerendy na DataRowCollection (właściwość DataTable.Rows), które prawdopodobnie nie używasz do niczego więcej niż listę DataRows. Zrobiłbym metodę rozszerzenia, która wykonuje tę transformację dla ciebie (DataRowCollection do List<DataRow>). Zwykle używam metody rozszerzania, aby bezpiecznie uzyskiwać wartości, gdy nie mam ochoty wyrzucić wyjątku, jeśli z jakiegoś powodu podano niepoprawną nazwę klucza dla kolumny. Następnie możesz utworzyć metodę rozszerzenia, która pobiera listę int jako id i nazwę pola zawierającego identyfikator, aby zwrócić to, co chcesz. Kiedy wszystko jest powiedziane i zrobione, robi się to za pomocą jednej linii kodu. Oto klasa z wszystkimi metodami rozszerzenia.

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

Następnie, inne niż konfigurowania zmiennych (który nie musiałby robić ... masz już im), prawdziwa praca odbywa się z jednej linii kodu (EDIT: jedno wywołanie metody):

 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); 
Powiązane problemy