You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C#编写API实现分页排序过滤,避免返回全量数据至前端

最优实现方案:C# API + KendoReact 网格 + Redux 大数据量处理

一、后端C# API 实现(分页+过滤+排序)

核心思路是让数据库层面完成分页、过滤、排序操作,避免全量数据加载。用EF Core的延迟查询特性,将前端参数转化为SQL语句执行。

1. 定义请求参数DTO

public class GridRequestDto
{
    public int PageIndex { get; set; } = 1;
    public int PageSize { get; set; } = 20;
    public string? Filter { get; set; }
    public string? SortField { get; set; }
    public string? SortDirection { get; set; } = "asc";
}

2. 控制器核心逻辑

[HttpPost("grid-data")]
public async Task<IActionResult> GetGridData([FromBody] GridRequestDto request)
{
    var query = _dbContext.TargetTable.AsQueryable();

    // 过滤逻辑(示例:多字段模糊匹配,可根据业务扩展)
    if (!string.IsNullOrEmpty(request.Filter))
    {
        var filterValue = request.Filter.ToLower();
        query = query.Where(x => 
            x.Field1.ToLower().Contains(filterValue) || 
            x.Field2.ToLower().Contains(filterValue));
    }

    // 排序逻辑(限制合法排序字段,防止SQL注入)
    var allowedSortFields = new List<string> { "Field1", "Field2", "Field3" };
    if (!string.IsNullOrEmpty(request.SortField) && allowedSortFields.Contains(request.SortField))
    {
        query = request.SortDirection?.ToLower() == "desc"
            ? query.OrderByDescending(x => EF.Property<object>(x, request.SortField))
            : query.OrderBy(x => EF.Property<object>(x, request.SortField));
    }

    // 分页查询:先统计总条数,再取当前页数据
    var totalCount = await query.CountAsync();
    var pageData = await query
        .Skip((request.PageIndex - 1) * request.PageSize)
        .Take(request.PageSize)
        .ToListAsync();

    return Ok(new { Total = totalCount, Data = pageData });
}

二、前端KendoReact 网格配置

利用KendoGrid内置的分页、过滤、排序事件,将状态变化同步到后端API,仅加载当前页数据。

核心组件实现

import { Grid, GridColumn } from '@progress/kendo-react-grid';
import { useSelector, useDispatch } from 'react-redux';
import { setGridData, setTotalCount, setGridLoading } from '../redux/gridSlice';

const DataGrid = () => {
    const { gridData, totalCount, isLoading } = useSelector(state => state.grid);
    const dispatch = useDispatch();

    // 统一处理分页/过滤/排序事件
    const handleGridStateChange = async (event) => {
        const { page, filter, sort } = event;
        
        // 构造后端请求参数
        const requestParams = {
            PageIndex: page.current + 1, // Kendo分页从0开始,后端从1开始
            PageSize: page.size,
            Filter: filter?.filters?.[0]?.value || '',
            SortField: sort?.[0]?.field || '',
            SortDirection: sort?.[0]?.dir || 'asc'
        };

        dispatch(setGridLoading(true));
        try {
            const response = await fetch('/api/yourcontroller/grid-data', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(requestParams)
            });
            const result = await response.json();
            dispatch(setGridData(result.Data));
            dispatch(setTotalCount(result.Total));
        } catch (err) {
            console.error('数据加载失败:', err);
        } finally {
            dispatch(setGridLoading(false));
        }
    };

    return (
        <Grid
            data={gridData}
            total={totalCount}
            pageable={{ pageSizes: [10, 20, 50] }}
            filterable={true}
            sortable={true}
            onPageChange={handleGridStateChange}
            onFilterChange={handleGridStateChange}
            onSortChange={handleGridStateChange}
            loading={isLoading}
        >
            <GridColumn field="Field1" title="字段1" />
            <GridColumn field="Field2" title="字段2" />
            {/* 其他列配置 */}
        </Grid>
    );
};

export default DataGrid;

三、Redux 状态管理优化

针对大数据场景,仅存储必要状态,避免冗余数据占用内存:

1. 初始状态设计

const initialState = {
    gridData: [], // 当前页数据
    totalCount: 0, // 总条数(用于分页计算)
    isLoading: false, // 加载状态
    currentParams: { // 记录当前请求参数,避免重复请求
        PageIndex: 1,
        PageSize: 20,
        Filter: '',
        SortField: '',
        SortDirection: 'asc'
    }
};

2. 关键优化点

  • 在handleGridStateChange中对比新参数与currentParams,参数无变化时跳过请求
  • 可选:添加缓存逻辑,对已请求过的页面数据进行缓存(需注意数据更新时清空缓存)

四、关键注意事项

  • 后端必须使用AsQueryable延迟查询,禁止先调用ToList()再在内存中处理数据
  • 排序字段需做白名单校验,防止SQL注入风险
  • 前端KendoGrid必须配置total属性,确保分页组件正常显示总页数
  • Redux仅存储当前页数据和总条数,不要保存全量数据

内容的提问来源于stack exchange,提问作者Baba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 05:03:35