2012-05-04 8 views
0

このクラスは、ページ作成のようなデータテーブルの一部を検索するために作成したものですが、すべて正常に機能しますが、メソッドは1つの列でフィルタリングできるという問題があります。 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()); 

私はこれをテストしていないので、AsEnumerable()ではなくを実行する必要があるのだろうか?

+0

COLUMNNAME、filterValueのプロパティを持つクラスを作成し、オペレータが、私はあなたのソリューションの仕事を考えて、おそらく最高の –

+0

@bradですが、それは私のために動作しません。私が望むように、私は私の質問のポイントを逃したと思う...しかし、とにかくあなたのソリューションを使用して、 'AND' ont he where節を使用しています。可能。とにかくtkx +1 – rpmlins

+0

@rpmlins、私はあなたのOR比較を行うのに役立つだろう 'PredicateBuilder'に関するいくつかの情報を追加しました。 –

0

私はあなたがパーサのいくつかの並べ替えが必要になると思います/ walkerを使用して文字列式をlinq式に変換します。一度それを持っていれば、それらのフィルタを適用することができます。 小さなlinqプロバイダのようなものが必要です。少なくとも、それが私の心に来るための唯一の方法だ...

1

ページネーションを行うクラスまたはメソッドでDataTableを照会しないでください。それはクラスの責任を破っている。これら2つの動作をむしろ分離する必要があります。

あなたはそのようにそれを行うことができます。今、そのコードが唯一のページングを気にされる

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

本当に好きです!!! – rpmlins