分页问题:返回正文中的总计数和总页数,而不添加到正在获取的其他数据

Posted

技术标签:

【中文标题】分页问题:返回正文中的总计数和总页数,而不添加到正在获取的其他数据【英文标题】:Pagination issue: returning total count and total pages in body, without adding to other data that is being fetched 【发布时间】:2021-11-16 17:31:32 【问题描述】:

我有一个搜索功能,我可以在其中填写 exempel 的值:注册号并获取有关它的数据,或者如果我不输入任何参数,我将获取所有数据,每页 100 行.现在,我还创建了一种计数,我可以在其中查看总共有多少行,以及如果每页有 100 行,这将是多少页。问题是我想返回请求正文中的总计数和总页数,例如,请求答案的外观如下:

[
    
        "claimHandlingStatus": "HANDLING",
        "requestDate": "2021-09-20",
        "requestID": 118095,
        "countryID": 1,
        "regNumber": "CNK258365",
        "produkt": "Produkt 54",
        "workshop": "Workshop 55",
        "asignee": null,
        "claimId": "387385",
        "vinnumber": ""
    ,
    
        "claimHandlingStatus": "HANDLING",
        "requestDate": "2021-09-203",
        "requestID": 118094,
        "countryID": 1,
        "regNumber": "CNK258365",
        "produkt": "Produkt 10",
        "workshop": "Workshop 3",
        "asignee": null,
        "claimId": "387384",
        "vinnumber": ""
    
]

而不是在每个答案中添加 2 行的总计数和总页数,我只想在正文中请求答案的顶部得到这些,所以它可能看起来像这样:

[
     
      "totalcount" : "300",
      "totalpages" : "3"
      ,
    
        "claimHandlingStatus": "HANDLING",
        "requestDate": "2021-09-20",
        "requestID": 118095,
        "countryID": 1,
        "regNumber": "CNK258365",
        "produkt": "Produkt 54",
        "workshop": "Workshop 55",
        "asignee": null,
        "claimId": "387385",
        "vinnumber": ""
    ,
    
        "claimHandlingStatus": "HANDLING",
        "requestDate": "2021-09-203",
        "requestID": 118094,
        "countryID": 1,
        "regNumber": "CNK258365",
        "produkt": "Produkt 10",
        "workshop": "Workshop 3",
        "asignee": null,
        "claimId": "387384",
        "vinnumber": ""
    
]

这是我使用的两种方法(一种用于搜索,一种用于计数)

public async Task<IEnumerable<GetRequestModelOut>> GetRequest(GetRequestModel model, int pageNumber = 1)

    var parameters = new DynamicParameters();
            
    parameters.Add("@RegNumber", model.RegNumber == string.Empty ? null : model.RegNumber);
    parameters.Add("@Vinnumber", model.Vinnumber == string.Empty ? null : model.Vinnumber);
    parameters.Add("@CountryID", model.CountryId == -1 ? (int?)null : model.CountryId);
    parameters.Add("@assigneid", model.AssigneId == string.Empty ? null : model.AssigneId);
    parameters.Add("@dateFrom", model.dateFrom); 
    parameters.Add("@dateTo", model.dateTo);
    parameters.Add("@pageSize", model.pageSize);
    parameters.Add("@PageNumber", model.PageNumber);

    int number = await getCount1(model);

    model.totalCount = number;
    model.totalPages = (int)Math.Ceiling(model.totalCount / (double)model.pageSize);

    var getReq1 = await _sqlconnection.QueryAsync<GetRequestModelOut>($@"
    SELECT model.totalCount as totalCount, model.totalPages as totalPages,
    ClaimHandlingStatus.Name as ClaimHandlingStatus,
    Request.CreatedDate as requestDate,
    Request.ID as RequestID, Contract.CountryID,
    RegNumber, Product.Name as produkt,
    Retailer.Name as workshop, Claim.CreatedBy as UserID, Claim.ID as claimId,
    Vinnumber
    FROM Request
    INNER JOIN RequestCrossClaim ON Request.ID = RequestCrossClaim.RequestID
    INNER JOIN Claim ON RequestCrossClaim.ClamID = Claim.ID
    INNER JOIN Contract ON Request.ContractID = Contract.ID
    INNER JOIN Vehicle ON Contract.VehicleID = Vehicle.ID
    INNER JOIN Product ON Contract.ProductID = Product.ID
    INNER JOIN Retailer ON Contract.RetailerID = Retailer.ID
    INNER JOIN ClaimHandlingStatus ON Claim.ClaimHandlingStatusID = ClaimHandlingStatus.ID
    where (@RegNumber IS NULL OR RegNumber = @Regnumber)                          
    AND (@Vinnumber IS NULL OR Vinnumber = @Vinnumber)                           
    AND (@CountryID IS NULL OR Contract.CountryID = @CountryID)                         
    AND (@assigneid IS NULL OR Claim.CreatedBy = @assigneid)
    AND (@dateFrom IS NULL OR Request.CreatedDate BETWEEN @dateFrom AND @dateTo)
    ORDER BY requestDate desc OFFSET @pageSize * (@PageNumber-1) ROWS FETCH NEXT @pageSize ROWS ONLY", 
    parameters);

    return getReq1;

这是计数:

public async Task<int> getCount1(GetRequestModel model)
   // Count method for Pagination in GetRequest
    var parameters = new DynamicParameters();
    parameters.Add("@RegNumber", model.RegNumber == string.Empty ? null : model.RegNumber);
    parameters.Add("@Vinnumber", model.Vinnumber == string.Empty ? null : model.Vinnumber);
    parameters.Add("@CountryID", model.CountryId == -1 ? (int?)null : model.CountryId);
    parameters.Add("@assigneid", model.AssigneId == string.Empty ? null : model.AssigneId);
    parameters.Add("@dateFrom", model.dateFrom);
    parameters.Add("@dateTo", model.dateTo);
    parameters.Add("@pageSize", model.pageSize);
    parameters.Add("@PageNumber", model.PageNumber);
    var getCount = await _sqlconnection.QueryAsync<int>($@"
    SELECT TOP 2000(Claim.ID)
    FROM Request
    INNER JOIN RequestCrossClaim ON Request.ID = RequestCrossClaim.RequestID
    INNER JOIN Claim ON RequestCrossClaim.ClamID = Claim.ID
    INNER JOIN Contract ON Request.ContractID = Contract.ID
    INNER JOIN Vehicle ON Contract.VehicleID = Vehicle.ID
    INNER JOIN Product ON Contract.ProductID = Product.ID
    INNER JOIN Retailer ON Contract.RetailerID = Retailer.ID
    INNER JOIN ClaimHandlingStatus ON Claim.ClaimHandlingStatusID = ClaimHandlingStatus.ID
    where (@RegNumber IS NULL OR RegNumber = @Regnumber)                          
    AND (@Vinnumber IS NULL OR Vinnumber = @Vinnumber)                           
    AND (@CountryID IS NULL OR Contract.CountryID = @CountryID)                         
    AND (@assigneid IS NULL OR Claim.CreatedBy = @assigneid)
    AND (@dateFrom IS NULL OR Request.CreatedDate BETWEEN @dateFrom AND @dateTo)
    ", parameters);
    return getCount.Count();

正如您在第一种方法中看到的,我目前正在将总计数和页面发送到模型,这意味着我当前的响应如下所示:

[
    
        "claimHandlingStatus": "HANDLING",
        "requestDate": "2021-09-20",
        "requestID": 118095,
        "countryID": 1,
        "regNumber": "CNK258365",
        "produkt": "Produkt 54",
        "workshop": "Workshop 55",
        "asignee": null,
        "claimId": "387385",
        "vinnumber": "",
        "totalCount": 2,
        "totalPages": 1
    ,
    
        "claimHandlingStatus": "HANDLING",
        "requestDate": "2021-09-203",
        "requestID": 118094,
        "countryID": 1,
        "regNumber": "CNK258365",
        "produkt": "Produkt 10",
        "workshop": "Workshop 3",
        "asignee": null,
        "claimId": "387384",
        "vinnumber": "",
        "totalCount": 2,
        "totalPages": 1
        
]

而且我认为这是不必要的,因为它足以获得总计数和页面一次。顺便说一下,模型的外观如下;

public class GetRequestModel

    public int CountryId  get; set;  = -1;
    public string AssigneId  get; set;  = "";

    [StringLength(50)]
    public string RegNumber  get; set;  = "";

    [StringLength(50)]
    public string Vinnumber  get; set;  = "";

    public DateTime? dateFrom  get; set;  = null;
    public DateTime? dateTo  get; set;  = null;

    // Pagination information
    public int pageSize  get; set;  = 100;
    public int PageNumber  get; set;  = 1;

    public int totalCount  get; set;  = 0;
    public int totalPages  get; set;  = 0;

以及获取数据的模型:

public class GetRequestModelOut

    public string ClaimHandlingStatus  get; set; 
    public DateTime RequestDate  get; set; 
    public int RequestID  get; set; 
    public int CountryID  get; set; 
    public string RegNumber  get; set; 
    public string Produkt  get; set; 
    public string Workshop  get; set; 
    public string Asignee  get; set; 
    public string claimId  get; set; 
    public string Vinnumber  get; set; 
    public int totalCount  get; set;  = 0;
    public int totalPages  get; set;  = 0;    

还有控制器:

[HttpGet]
public async Task<IActionResult> GetRequest([FromQuery] GetRequestModel model, int pageNumber) 

    if (!ModelState.IsValid)
    
        return BadRequest(ModelState);
    
    try
    
        var list = await _request.GetRequest(model, pageNumber);
        return Ok(list);
    
    catch (Exception e)
    
        return BadRequest(e.Message);
    
            
    return Ok();

现在我尝试做一些类似的事情:

 var metadata = new
 
     model.totalCount,
     model.totalPages
 ;

在控制器中,但这仍然留下了关于如何将这两个值返回到响应 body 的问题?感谢您的任何意见,因为我现在感觉有点卡住了。

【问题讨论】:

This discussion 似乎解释了如何确定总行数(结果集中的TempCount 列)而不会在大型数据集上出现性能问题 @Pieterjan 谢谢你,我会调查的。我在数据库上创建了 indexex,所以性能还可以而且不慢,但它可能会更好,在不同的方法上选择和计算相同的查询并不是最好的主意哈哈 【参考方案1】:

我认为,更好的解决方案是将所有这些答案+摘要详细信息实际包装在单独的对象中,将它们组合在一起。喜欢:

public class SummaryModel

    public int totalCount  get; set;  = 0;
    public int totalPages  get; set;  = 0;


public class GetRequestModelOut

    // Things from your normal out-model
    // WITHOUT totalCount and totalPages


public class ResultModel

    public SummaryModel Summary  get; set; 
    public IEnumerable<GetRequestModelOut> Models  get; set; 


当您将调用/返回结果时,您只需将对象放在一起,如下所示:

public async Task<ResultModel> GetRequest(GetRequestModel model, int pageNumber = 1)

    var parameters = new DynamicParameters();
            
    parameters.Add("@RegNumber", model.RegNumber == string.Empty ? null : model.RegNumber);
    parameters.Add("@Vinnumber", model.Vinnumber == string.Empty ? null : model.Vinnumber);
    //add all other params

    int totalCount = await getCount1(model);
    int totalPages = (int)Math.Ceiling(totalCount / (double)model.pageSize);
    var summary = new Summary()
    
        totalCount = totalCount,
        totalPages = totalPages
    ;

    var models = await _sqlconnection.QueryAsync<GetRequestModelOut>(/*query*/);
    
    return new ResultModel()
    
        Summary = summary,
        Models = models
    ;


生成的 JSON 如下所示:


    "Summary": 
        "totalCount": 300,
        "totalPages": 3
    ,
    "Models": [
    
        "claimHandlingStatus": "HANDLING",
        "requestDate": "2021-09-20",
        "requestID": 118095,
        "countryID": 1,
        "regNumber": "CNK258365",
        "produkt": "Produkt 54",
        "workshop": "Workshop 55",
        "asignee": null,
        "claimId": "387385",
        "vinnumber": ""
    ,
    
        "claimHandlingStatus": "HANDLING",
        "requestDate": "2021-09-203",
        "requestID": 118094,
        "countryID": 1,
        "regNumber": "CNK258365",
        "produkt": "Produkt 10",
        "workshop": "Workshop 3",
        "asignee": null,
        "claimId": "387384",
        "vinnumber": ""
    ]

【讨论】:

【参考方案2】:

你的预期输出是关闭考虑这个:


    "totalcount" : "300",
    "totalpages" : "3",
    "items" : [
        
            "claimHandlingStatus": "HANDLING",
            "requestDate": "2021-09-20",
            "requestID": 118095,
            "countryID": 1,
            "regNumber": "CNK258365",
            "produkt": "Produkt 54",
            "workshop": "Workshop 55",
            "asignee": null,
            "claimId": "387385",
            "vinnumber": ""
        ,
        
            "claimHandlingStatus": "HANDLING",
            "requestDate": "2021-09-203",
            "requestID": 118094,
            "countryID": 1,
            "regNumber": "CNK258365",
            "produkt": "Produkt 10",
            "workshop": "Workshop 3",
            "asignee": null,
            "claimId": "387384",
            "vinnumber": ""
        
    ]

总计数和总页数不应是项目的一部分。不过,这样你发送的是一个作业而不是一个 jarray。

【讨论】:

以上是关于分页问题:返回正文中的总计数和总页数,而不添加到正在获取的其他数据的主要内容,如果未能解决你的问题,请参考以下文章

怎样使word页码中的总页数不包括封面和目录(文章正文中包含很多节)

Asp.net的DataPager控件如何显示当前页的数据条数、总条数和总页数?

Codeigniter 分页显示结果数和页数

jquery ajax 调用kkpager插件 异步加载重新生成分页后,点击页数还是跟首次加载一样

jqgrid 如何获取分页的信息:当前页和总页数,作为参数传递到url

未解决mysql分页性能问题深究