带有存储过程的服务器端剑道分页

Posted

技术标签:

【中文标题】带有存储过程的服务器端剑道分页【英文标题】:Server side kendo paging with stored procedures 【发布时间】:2015-11-20 23:52:10 【问题描述】:

我想使用[DataSourceRequest] DataSourceRequest requestToDataSourceResult 实现服务器端分页/排序/等

我已经使用 LINQ 和 EF 完成了数百次,但是,当前的项目要求我们使用存储过程,由 context.Database.SqlQuery 调用

这很好用,除非我还需要将参数传递到存储过程中,这会导致错误:

SqlParameter 已被另一个 SqlParameterCollection 包含。

我认为这是因为 Kendo 的 ToDataSourceResult 还试图将 SQL 参数附加到 C# 不喜欢的 data 对象。

我在网上看到的一些解决方案是调用.ToList(),这确实有效,但是,它有点失败,因为它仍然会查询所有结果。

var data = context.Database.SqlQuery<TicketVm>("usp_FleetRentedEquipments @analyst",
                                               new SqlParameter("@analyst", analyst));
return data.ToDataSourceResult(request);

【问题讨论】:

我也遇到了同样的问题...你解决了吗? 是的,我也需要这个答案 【参考方案1】:

在 ToDataSourceResult 方法中,查询至少使用了两次——一次是调用 Count(),一次是提取数据。这会导致使用 SQL 参数集两次的错误。您可能只能这样做:

var data = context.Database.SqlQuery<TicketVm>($"usp_FleetRentedEquipments analyst");
return data.ToDataSourceResult(request);

并且要非常小心,'analyst' 不是 SQL 注入。

【讨论】:

【参考方案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

【讨论】:

什么是动态参数? 可以改用普通的sql参数吗? 你有没有想办法在没有第三方控制的情况下做到这一点?我不能用这个,因为它需要钱才能使用这个控件。 如果您指的是 Dapper,那么它是免费的。如果需要,您可以使用标准 SqlParameters。

以上是关于带有存储过程的服务器端剑道分页的主要内容,如果未能解决你的问题,请参考以下文章

kendo ui grid 完成服务器端分页和设置总数

剑道网格服务器端过滤和不工作

s-s-rS报表中服务器端分页的逻辑是啥

分页剑道网格客户端

如果启用了无限滚动,如何防止剑道网格两次加载数据?

如何在引导表中使用带有 ajax 的服务器端分页?