LINQ过滤器可通过n列进行数据表

时间:2012-05-04 14:42:12

标签: c# .net linq datatable

我已经让这个类像分页那样检索一个数据表的部分,一切正常,但问题是该方法只能过滤一列,我没有想法使用LINQ来存档它。我希望传递n列和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 个答案:

答案 0 :(得分: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()

答案 1 :(得分: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);

答案 2 :(得分:0)

我认为你需要某种解析器/ walker来将你的字符串表达式转换为linq表达式。一旦你有了,你将能够应用这些过滤器。 你需要像一个小的linq提供者。至少那是我想到的唯一方法......