【问题标题】:Bind a database table with Kendo Grid (MVC) using stored procedure, with large amounts of data with proper server side paging, sorting, filtering使用存储过程将数据库表与 Kendo Grid (MVC) 绑定,具有大量数据并具有适当的服务器端分页、排序、过滤
【发布时间】:2017-04-08 14:57:31
【问题描述】:

我们有一个包含大量数据(数百万行)的表。我们正在使用存储过程来获取记录并使用 mvc 方法将该数据与剑道网格绑定。但我们只想从表中获取所需的行,而不是一次性获取整组数据,然后对其进行过滤、排序、分页选项。

是否可以一次只获取一页行?请帮助并提出一些方法。

【问题讨论】:

  • 类似.ServerFiltering(true)
  • 你的问题太宽泛了......也许你应该从阅读剑道的文档开始。

标签: sql-server asp.net-mvc kendo-ui kendo-grid kendo-asp.net-mvc


【解决方案1】:

首先,您的存储过程中应该有一些分页逻辑。您可以查看这篇博文以获取建议:https://sqlperformance.com/2015/01/t-sql-queries/pagination-with-offset-fetch

然后,在您的视图中,将网格的数据源设置为调用控制器中的自定义操作。确保启用分页。像这样的:

.Pageable()
.DataSource(dataSource => dataSource
        .Ajax()
        .Read(read => read.Action("CustomAjaxBinding_Read", "Grid"))
    )

最后在您的控制器中创建操作并使其期望 DataSourceRequest 参数。该参数将从网格接收一个对象,其中包括页面大小和当前页码。您可以使用它们将它们传递给您的存储过程,并使其仅获取该数据页。它会是这样的:

public ActionResult CustomAjaxBinding_Read([DataSourceRequest] DataSourceRequest request)
        {
            // Get the page number and size, which the grid is requesting
            var pageNumber = request.Page;
            var pageSize = request.PageSize;

            // Call your stored procedure here
            // ...

            // Now return the data to the grid, formatted as JSON
            return Json(result);
        }

您可以在 Telerik 的网站上查看 ajax 数据源示例:查看 http://demos.telerik.com/aspnet-mvc/grid/customajaxbinding

【讨论】:

  • 这正是我想要实现的,但我还是想问,我们可以有 Iqueryable 存储过程吗?
  • 只是为了向你展示我的初步工作:string filterLogic = ""; if (request.Filters.Any()) { foreach (var filter in request.Filters) { var descriptor = filter as FilterDescriptor; filterLogic = " where " + descriptor.Member + " = '" + descriptor.Value + "'"; } }
  • 您的代码建议您让存储过程返回所有内容,然后您将对其应用过滤器/分页。这可能效率不高。为什么不在存储过程中构建过滤逻辑,然后将成员和值作为参数发送,例如stackoverflow.com/questions/697671/…。您可以将 OFFSET 和 FETCH NEXT 用于分页逻辑。
【解决方案2】:

我刚刚这样做了(注意:我使用的是 Dapper 和 EF)

var gridBinder = new GridBinder(request);

var filters = gridBinder.GetFilterDescriptor();

var sorting = gridBinder.SortInfo.Member.HasValue() ? string.Format("{0} {1}", gridBinder.SortInfo.Member, gridBinder.SortInfo.Direction) : "";

var p = new DynamicParameters();
p.Add("@Page", gridBinder.PageNumber, DbType.Int32, ParameterDirection.Input);
p.Add("@PageSize", gridBinder.PageSize, DbType.Int32, ParameterDirection.Input);
p.Add("@Filter", filters);
p.Add("@SortOrder", sorting);
p.Add("@TotalRowCount", dbType: DbType.Int32, direction: ParameterDirection.Output);

var data = _db.Connection().Query<IndexVm>("dbo.People_GetAll", p, commandType: System.Data.CommandType.StoredProcedure, transaction: _db.Database.CurrentTransaction.GetDbTransaction());

gridBinder.RecordCount = data.FirstOrDefault().TotalRowCount;

return Json(new DataSourceResult
{
    Total = gridBinder.RecordCount,
    Data = data
});

网格绑定器

public class GridBinder
{
    public int PageNumber { get; set; } = 1;

    public int PageSize { get; set; } = 10;

    public int RecordCount { get; set; }

    public SortInfo SortInfo { get; set; } = new SortInfo() { Direction = SortDirection.Asc, Member = string.Empty };

    private readonly DataSourceRequest _command;

    public GridBinder(DataSourceRequest command)
    {
        _command = command;
        PageNumber = command.Page;
        PageSize = command.PageSize;
        GetSortDescriptor();
    }

    private void GetSortDescriptor()
    {
        foreach (SortDescriptor descriptor in _command.Sorts)
        {
            SortInfo.Member = descriptor.Member;
            SortInfo.Direction = descriptor.SortDirection == ListSortDirection.Ascending ? SortDirection.Asc : SortDirection.Desc;
        }
    }

    public string GetFilterDescriptor()
    {
        string filters = string.Empty;
        foreach (IFilterDescriptor filter in _command.Filters)
        {
            filters += ApplyFilter(filter);
        }

        return filters;
    }

    private static string ApplyFilter(IFilterDescriptor filter)
    {
        var filters = "";
        if (filter is CompositeFilterDescriptor)
        {
            filters += "(";
            var compositeFilterDescriptor = (CompositeFilterDescriptor)filter;
            foreach (IFilterDescriptor childFilter in compositeFilterDescriptor.FilterDescriptors)
            {
                filters += ApplyFilter(childFilter);
                filters += " " + compositeFilterDescriptor.LogicalOperator.ToString() + " ";
            }
        }
        else
        {
            string filterDescriptor = "{0} {1} {2}";
            var descriptor = (FilterDescriptor)filter;
            if (descriptor.Operator == FilterOperator.StartsWith)
            {
                filterDescriptor = string.Format(filterDescriptor, descriptor.Member, "LIKE", "'" + descriptor.Value + "%'");
            }
            else if (descriptor.Operator == FilterOperator.EndsWith)
            {
                filterDescriptor = string.Format(filterDescriptor, descriptor.Member, "LIKE", "'%" + descriptor.Value + "'");
            }
            else if (descriptor.Operator == FilterOperator.Contains)
            {
                filterDescriptor = string.Format(filterDescriptor, descriptor.Member, "LIKE", "'%" + descriptor.Value + "%'");
            }
            else if (descriptor.Operator == FilterOperator.DoesNotContain)
            {
                filterDescriptor = string.Format(filterDescriptor, descriptor.Member, "NOT LIKE", "'%" + descriptor.Value + "%'");
            }
            else if (descriptor.Operator == FilterOperator.IsEqualTo)
            {
                filterDescriptor = string.Format(filterDescriptor, descriptor.Member, "=", "'" + descriptor.Value + "'");
            }
            else if (descriptor.Operator == FilterOperator.IsNotEqualTo)
            {
                filterDescriptor = string.Format(filterDescriptor, descriptor.Member, "<>", "'" + descriptor.Value + "'");
            }
            else if (descriptor.Operator == FilterOperator.IsGreaterThan)
            {
                filterDescriptor = string.Format(filterDescriptor, descriptor.Member, ">", "'" + descriptor.Value + "'");
            }
            else if (descriptor.Operator == FilterOperator.IsGreaterThanOrEqualTo)
            {
                filterDescriptor = string.Format(filterDescriptor, descriptor.Member, ">=", "'" + descriptor.Value + "'");
            }
            else if (descriptor.Operator == FilterOperator.IsLessThan)
            {
                filterDescriptor = string.Format(filterDescriptor, descriptor.Member, "<", "'" + descriptor.Value + "'");
            }
            else if (descriptor.Operator == FilterOperator.IsLessThanOrEqualTo)
            {
                filterDescriptor = string.Format(filterDescriptor, descriptor.Member, "<=", "'" + descriptor.Value + "'");
            }

            filters = filterDescriptor;
        }

        filters = filters.EndsWith("And ") == true ? filters.Substring(0, filters.Length - 4) + ")" : filters;
        filters = filters.EndsWith("Or ") == true ? filters.Substring(0, filters.Length - 4) + ")" : filters;

        return filters;
    }
}
public class SortInfo
{
    public string Member { get; set; }
    public SortDirection Direction { get; set; }
}

public enum SortDirection
{
    Asc, Desc
}

【讨论】:

  • Tim 您如何为这些参数设置存储过程?可以发一下吗
猜你喜欢
  • 1970-01-01
  • 2019-04-30
  • 2021-10-20
  • 1970-01-01
  • 1970-01-01
  • 2019-08-23
  • 1970-01-01
  • 2020-01-22
  • 1970-01-01
相关资源
最近更新 更多