0

我已经让这个类像分页一样检索数据表的一部分,一切正常,但问题是该方法只能按一列过滤,我不知道如何使用 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();
    }
}
4

3 回答 3

3

删除参数columnFilterand并将您的数据传递到andexpression的集合中。您可以创建一个自定义类或只使用这样的列表 :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。那是破坏班级的责任。您应该将这两种行为分开。

你可以这样做:

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

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

于 2012-05-04T15:01:36.447 回答