我已经让这个类像分页那样检索一个数据表的部分,一切正常,但问题是该方法只能过滤一列,我没有想法使用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();
}
}
答案 0 :(得分:3)
删除参数columnFilter
和expression
,然后将您的数据传递到columnsFilter
和expression
的集合中。您可以创建自定义类或只使用列表
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提供者。至少那是我想到的唯一方法......