0

このクラスは、ページ付けなどのデータテーブルの一部を取得するために作成しました。すべてが正常に機能しますが、問題は、メソッドが1つの列でしかフィルタリングできないことです。これを、LINQを使用してアーカイブするためのアイデアはありません。フィルタリングするn列とn式を渡したいと思いました。

例:列:名前、式'jonh'列:都市、式'florida'

これが私のクラスです:

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

3 に答える 3

3

パラメータcolumnFilterを削除し、代わりにとexpressionのコレクションでデータを渡します。カスタムクラスを作成することも、次のようなリストを使用することもできます 。columnsFilterexpressionTuple<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()か?

于 2012-05-04T15:32:07.683 に答える
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;
    }
}

この場合、クラスの動作を拡張しているだけで、読みやすくなっているため、Extensionメソッドとして使用しました。

そして、次のようにしてコードを使用できます。

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);
于 2012-05-04T17:22:58.697 に答える
0

文字列式をlinq式に変換するには、ある種のパーサー/ウォーカーが必要になると思います。それができたら、それらのフィルターを適用できるようになります。小さなlinqプロバイダーのようなものが必要です。少なくともそれが私の頭に浮かぶ唯一の方法です...

于 2012-05-04T15:01:36.447 に答える