2012-05-04 83 views
0

我已經使這個類檢索數據表的部分像分頁,一切工作正常,但問題是,該方法只能過濾一列,我沒有ideia hwo歸檔這使用LINQ。我想通過n列和n表達式進行過濾。LINQ篩選器Datatable by n列

例如: 列:姓名,表達 'jonh' 柱:城市,表達 '佛羅里達'

這裏是我的類:

public class Paging 
{ 
    public enum Operator 
    { 
     Equal, 
     Like 
    } 

    public static DataTable Page(DataTable dataTableToPage, int pageSize, int pageNumber, string columnToFilter, string expression, out int totalrecords, Operator Operator) 
    { 
     int skip = (pageNumber - 1) * pageSize; 


     IEnumerable<DataRow> query = null; 

     if (Operator == Operator.Equal) 
     { 
      query = (from dr in dataTableToPage.AsEnumerable() 
        where dr[columnToFilter].ToString() == expression 
        select dr); 
     } 
     else if(Operator == Operator.Like) 
     { 
      query = (from dr in dataTableToPage.AsEnumerable() 
        where dr[columnToFilter].ToString().IndexOf(expression, StringComparison.OrdinalIgnoreCase) >= 0 
        select dr); 
     } 

     var queryConverted = query.Skip(skip).Take(pageSize); 

     if (queryConverted.Count() > 0) 
     { 
      totalrecords = query.Count(); 

      return queryConverted.CopyToDataTable(); 

     } 

     totalrecords = 0; 

     return new DataTable(); 
    } 
} 

回答

3

刪除參數columnFilterexpression,而是將您的數據傳遞給columnsFilterexpression的集合。您可以創建一個自定義的類或者只是使用這樣的 Tuple<string,string>列表:

public static DataTable Page(DataTable dataTableToPage, int pageSize, int pageNumber, 
    IList<Tuple<string, string>> columnToExpression, 
    out int totalrecords, Operator Operator) 

要創建你正在做這樣的事情元組:

var colsExps = new List<Tuple<string, string>>(); 
colsExps.Add(new Tuple<string,string>("Name", "John")); 
colsExps.Add(new Tuple<string,string>("City", "Miami")); 

然後修改代碼在查詢中是這樣的:

if (Operator == Operator.Equal)  
{  
    query = (from dr in dataTableToPage.AsEnumerable()  
       select dr);  
    foreach (var pair in columnToExpression) 
    { 
     string columnFilter = pair.Item1; 
     string expression = pair.Item2; 
     query = query.Where (dr => dr[columnFilter].ToString() == expresion); 
    }  
}  
else if(Operator == Operator.Like)  
{  
    query = (from dr in dataTableToPage.AsEnumerable()  
       select dr);  
    foreach (var pair in columnToExpression) 
    { 
     string columnFilter = pair.Item1; 
     string expression = pair.Item2; 
     query = query.Where (dr => dr[columnToFilter].ToString().IndexOf(expression, 
        StringComparison.OrdinalIgnoreCase) >= 0); 
    }  
}  

或者,你可以使用PredicateBuilder

query = (from dr in dataTableToPage.AsEnumerable()  
      select dr);  

// I'm not sure exactly what T you should be using in the following statement: 
// DataRow should be the type of dr 
var predicate = PredicateBuilder.False<DataRow>(); 

foreach (var pair in columnToExpression) 
{ 
    string columnFilter = pair.Item1; 
    string expression = pair.Item2; 
    predicate = predicate.Or(dr => dr[columnFilter].ToString() == expresion); 
}  

query = query.Where(predicate.Compile()); 

由於我沒有測試過這個,不知您是否需要做dataTableToPage.AsQueryable()而不是AsEnumerable()

+0

創建與列名,filterValue屬性的類,和運營商可能是最好 –

+0

@brad我認爲您的解決方案的工作,但它不爲我工作正如我想的那樣,我認爲我錯過了我的問題上的一點......但無論如何用你的解決方案,就像在where子句中使用'AND'一樣,如果我想用'OR'得到一個結果可能。但無論如何tkx +1 – rpmlins

+0

@rpmlins,我已經添加了一些關於'PredicateBuilder'的信息,它可以幫助你做OR比較。 –

0

我想你會需要某種形式的解析器/ walker將你的字符串表達式轉換成linq表達式。一旦你有,你將能夠應用這些過濾器。 你需要像一個微小的linq提供者。至少這是我想到的唯一方法......

1

您不應該在您想要分頁的類或方法中查詢您的DataTable。這打破了班級的責任。你應該將這兩種行爲分開。

你可以那樣做:

public static class Paging 
{ 
    public static DataTable Page(this IEnumerable<DataRow> dataTableQuery, int pageSize, int pageNumber, out int totalrecords) 
    { 
     int skip = (pageNumber - 1) * pageSize; 

     var queryConverted = dataTableQuery.Skip(skip).Take(pageSize); 

     if (queryConverted.Count() > 0) 
     { 
      totalrecords = query.Count(); 

      return queryConverted.CopyToDataTable(); 
     } 
     totalrecords = 0; 

     return new DataTable(); 
    } 
} 

現在,代碼只關心分頁。

而對於查詢:

public static class DataTableQuery 
{ 
    public static IEnumerable<DataRow> Where(this DataTable dataTable, string columnName, string expression) { 
     return from dr in dataTableToPage.AsEnumerable() 
        where dr[columnToFilter].ToString() == expression 
        select dr; 
    } 

    public static IEnumerable<DataRow> Like(this DataTable dataTable, string columnName, string expression) { 
     return from dr in dataTableToPage.AsEnumerable() 
        where dr[columnToFilter].ToString().IndexOf(expression, StringComparison.OrdinalIgnoreCase) >= 0 
        select dr; 
    } 
} 

我做了他們作爲擴展方法,因爲在這種情況下,你只是擴展該類行爲和他們很好地閱讀。

而且你可以通過執行使用代碼:

int totalRecords = 0; 
DataTable dataTable = ...; 
var page = dataTable.Where("Name", "Jhon").Page(1, 1, out totalRecords); 
var page = dataTable.Like("City", "florida").Page(2, 3, out totalRecords); 
+0

感謝您的建議@Adauto !!因爲我的代表太低,我不能投票!但thx很多 – rpmlins

+0

沒問題!我只是想知道,分離的擔憂,你可以添加許多「過濾器」因爲你沒有改變它,我希望你看到這個優點,我希望你喜歡這個解決方案。 – Adauto

+0

我真的很喜歡!!! thx !!! – rpmlins