65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 ASP.NET Core 和 Angular 8 进行服务器端分页

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (3投票s)

2020 年 1 月 9 日

CPOL

5分钟阅读

viewsIcon

10159

在本文中,我们将学习如何创建服务器端分页,这在我们需要显示大量记录时非常有用。

引言

这是一个由三部分组成的系列文章,在本文中,我们将显示记录数,并计算总页数,但每页只能看到选定的记录。因此,我们不会一次性获取所有记录,而是会根据页面获取记录,这将提高我们的性能。

它将如何工作?

假设我们要前端显示 500 条记录,并且每页只显示 100 条记录。当您单击第 2 页时,它将显示接下来的 100 条记录,依此类推。在 Angular 中,我们可以使用管道并安装一些软件包来显示分页,但是如果我们一次只显示 100 条记录,那么我们为什么要获取全部 500 条记录呢?这会降低我们的性能。

因此,一次只获取 100 条记录,然后在单击下一页时,获取该特定页面的下一 100 条记录会更好。这里,每次单击页面时,都会从数据库表中获取记录。

必备组件

  • 具备 Angular 的基础知识
  • 必须安装 Visual Studio Code
  • 必须安装 Angular CLI
  • 必须安装 Node JS
  • 必须安装 Microsoft Visual Studio 2017
  • SQL Server 2014。

Using the Code

后端

在这里,我们将使用 SQL Server 进行后端相关的代码编写。

第一步是创建一个数据库。

步骤 1

create database company 

让我们在本地 SQL Server 上创建一个数据库。我希望您已在机器上安装了 SQL Server 2017(您也可以使用 SQL Server 2008、2012 或 2016)。

第二步

使用以下代码创建 CompanyDetails

CREATE TABLE [dbo].[CompanyDetails](  
    [CompanyId] [int] IDENTITY(1,1) NOT NULL,  
    [CompanyName] [nvarchar](100) NULL,  
    [City] [nvarchar](50) NULL,  
    [State] [nvarchar](50) NULL,  
    [Owner] [nvarchar](50) NULL,  
    [PublishYear] [int] NULL,  
 CONSTRAINT [PK_CompanyDetails] PRIMARY KEY CLUSTERED   
(  
    [CompanyId] ASC  
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, _
 IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]  
) ON [PRIMARY]  
GO  

现在让我们添加存储过程。

步骤 3

创建以下存储过程

GetAllCompanies
Create Proc [dbo].[Usp_GetAllCompanies]  
 @PageNo INT ,  
 @PageSize INT ,  
 @SortOrder VARCHAR(200)  
As  
Begin  
  
    Select * From   (Select ROW_NUMBER() Over (  
    Order by CompanyName ) AS 'RowNum', *  
         from   [CompanyDetails]  
        )t  where t.RowNum Between ((@PageNo-1)*@PageSize +1) AND (@PageNo*@pageSize)  
        
End
GetAllCompaniesCount
Create Proc [dbo].[Usp_getAllCompaniesCount]  
As  
  
Begin  
        select count(CompanyId) from   [CompanyDetails]  
End

Web API

创建一个 ASP.NET Core 应用程序。

请按照以下步骤创建 ASP.NET Core 应用程序。

步骤 1

在 Visual Studio 2019 中,单击 文件 -> 新建 -> 项目

Server Side Pagination Using ASP.NET Core And Angular 8

第二步

选择 创建 选项并选择 ASP.NET Web 应用程序。

Server Side Pagination Using ASP.NET Core And Angular 8

步骤 3

选择 Web API,然后单击 确定

Server Side Pagination Using ASP.NET Core And Angular 8

步骤 4

现在右键单击控制器,然后添加一个新项。

Server Side Pagination Using ASP.NET Core And Angular 8

步骤 5

选择 ADO.NET Entity Data Model,然后单击 添加

Server Side Pagination Using ASP.NET Core And Angular 8

步骤 6

下一步是 EF Designer,只需单击 下一步

Server Side Pagination Using ASP.NET Core And Angular 8

步骤 7

将显示一个新弹出窗口。单击 下一步。如果您的连接未建立,请单击新建连接。

Server Side Pagination Using ASP.NET Core And Angular 8

步骤 8

复制数据库连接服务器名称并将其粘贴到服务器名称 文本框 中。您将看到所有数据库,选择您的数据库,然后单击 确定

Server Side Pagination Using ASP.NET Core And Angular 8

步骤 9

将显示下一个弹出窗口,粘贴数据库服务器名称,选择数据库并测试连接,然后单击 下一步。在这里,在新屏幕中,选择您的表和存储过程。然后单击 完成

Server Side Pagination Using ASP.NET Core And Angular 8

下一步是右键单击 controllers 文件夹并添加一个新控制器。将其命名为“Paginationcontroller”,并在 Paginationcontroller 中添加以下命名空间。

这是获取所有分页记录的完整代码。

完整的 Paging Controller 代码

using System.Collections.Generic;  
using System.Data.Entity.Core.Objects;  
using System.Linq;  
using System.Web.Http;  
using Pagination.Models;  
namespace Pagination.Controllers  
{  
    public class PaginationController : ApiController  
    {  
        CompanyEntities2 db = new CompanyEntities2();  
  
        [HttpGet]  
        public object getAllCompanies(int pageNo, int pageSize, string sortOrder)  
        {  
  
            var oMyString = new ObjectParameter("totalCount", typeof(int));  
  
            var companyDetails = db.Usp_GetAllCompanies(pageNo, pageSize, sortOrder).ToList();  
            return companyDetails;  
        }  
  
        [HttpGet]  
        public object getAllCompaniesCount()  
        {  
  
            var companyDetailsCount = db.Usp_getAllCompaniesCount().SingleOrDefault();         
            return companyDetailsCount;  
        }  
    }  
} 

前端

步骤 1

让我们使用以下 npm 命令创建一个 Angular 项目

ng new pagination

第二步

在 Visual Studio Code 中打开新创建的项目,并在该项目中 安装 bootstrap

npm install bootstrap --save   

现在打开 styles.css 文件并添加 Bootstrap 文件引用。要在 styles.css 文件中添加引用,请添加此行

@import '~bootstrap/dist/css/bootstrap.min.css';  

步骤 3

现在让我们使用以下命令创建一个新组件

ng g c pagination  

步骤 4

现在使用以下命令创建一个新服务

ng generate service pagination   

步骤 5

现在打开 pagination.component.html 并粘贴以下代码以查看 HTML 模板。

<div class="row">    
  <div class="col-12 col-md-12">    
    <div class="card">    
      <div class="card-header">    
        Companies 1-{{pageSize}} (Total:{{totalCompaniesCount}})    
      </div>    
      <div class="card-body position-relative">    
           
        <div class="table-responsive cnstr-record companie-tbl">    
          <table class="table table-bordered heading-hvr">    
            <thead>    
              <tr>    
                <th style="cursor: pointer;" [ngClass]="order =='CompanyNumber'? 'active':''"    
                  (click)="setOrder('CompanyNumber')" width="80">Company Name.</th>    
                <th style="cursor: pointer;" [ngClass]="order =='CompanyType'? 'active':''"    
                  (click)="setOrder('CompanyType')" width="75">City</th>    
                <th [ngClass]="order =='CompanyName'? 'active':''" style="cursor: pointer;"    
                  (click)="setOrder('CompanyName')">State    
                </th>    
                <th [ngClass]="order =='OrgNo'? 'active':''" 
                 style="cursor: pointer;" (click)="setOrder('OrgNo')"    
                  width="75">Owner    
                </th>    
                <th [ngClass]="order =='Street'? 'active':''" 
                 style="cursor: pointer; width:250px"    
                  (click)="setOrder('Street')">Publish Year</th>    
              </tr>    
            </thead>    
            <tbody>    
              <tr *ngFor="let item of companies">    
                <td>{{item.CompanyName}}</td>    
                <td>{{item.City}}</td>    
                <td>{{item.State}}</td>    
                <td>{{item.Owner}}</td>    
                <td>{{item.PublishYear}}</td>    
    
              </tr>    
            </tbody>    
          </table>      
              
        </div>    
        <!-- Code by pagination -->    
        <div class="container mw-100">    
          <div class="row">    
            <div class="col-md-3"> </div>    
            <div *ngIf="companies !=0" class="col-md-6">    
              <ul class="pagination justify-content-center">    
                <li *ngFor="let page of pageField;let i=index" class="page-item">    
                  <a (click)="showCompaniesByPageNumber(page,i)" 
                  [ngClass]="pageNumber[i] ? 'pageColor':'page-link'"    
                    style=" margin-right: 5px;;margin-top: 5px">{{page}}    
                       
                </li>    
              </ul>    
              <div style="text-align: center;">    
                Page {{currentPage}} of Total page {{paginationService.exactPageList}}    
              </div>    
            </div>    
          </div>    
        </div>    
      </div>    
    </div>    
  </div>    
</div>

步骤 6

之后,打开 pagination.component.ts 文件,并在其中编写逻辑的文件中添加以下代码。

import { Component, OnInit } from '@angular/core';  
import { ApiService } from './api.service';  
import { PaginationService } from './pagination.service';  
  
@Component({  
  selector: 'app-pagination',  
  templateUrl: './pagination.component.html',  
  styleUrls: ['./pagination.component.css']  
})  
export class PaginationComponent implements OnInit {  
  companies = [];  
  pageNo: any = 1;  
  pageNumber: boolean[] = [];  
  sortOrder: any = 'CompanyName';  
  //Pagination Variables  
  
  pageField = [];  
  exactPageList: any;  
  paginationData: number;  
  companiesPerPage: any = 5;  
  totalCompanies: any;  
  totalCompaniesCount: any;  
  
  constructor(public service: ApiService, public paginationService: PaginationService) { }  
  
  ngOnInit() {  
    this.pageNumber[0] = true;  
    this.paginationService.temppage = 0;  
    this.getAllCompanies();  
  }  
  getAllCompanies() {  
    this.service.getAllCompanies
    (this.pageNo, this.companiesPerPage, this.sortOrder).subscribe((data: any) => {  
      this.companies = data;  
      this.getAllCompaniesCount();  
    })  
  }  
  
  //Method For Pagination  
  totalNoOfPages() {  
  
    this.paginationData = Number(this.totalCompaniesCount / this.companiesPerPage);  
    let tempPageData = this.paginationData.toFixed();  
    if (Number(tempPageData) < this.paginationData) {  
      this.exactPageList = Number(tempPageData) + 1;  
      this.paginationService.exactPageList = this.exactPageList;  
    } else {  
      this.exactPageList = Number(tempPageData);  
      this.paginationService.exactPageList = this.exactPageList  
    }  
    this.paginationService.pageOnLoad();  
    this.pageField = this.paginationService.pageField;  
  
  }  
  showCompaniesByPageNumber(page, i) {  
    this.companies = [];  
    this.pageNumber = [];  
    this.pageNumber[i] = true;  
    this.pageNo = page;  
    this.getAllCompanies();  
  }  
  
  getAllCompaniesCount() {  
    this.service.getAllCompaniesCount().subscribe((res: any) => {  
      this.totalCompaniesCount = res;  
      this.totalNoOfPages();  
    })  
  }   
}

步骤 7

接下来打开 pagination.component.css 文件并粘贴代码以进行一些样式设置。

@charset "utf-8";     
/* CSS Document */    
@media all{    
    *{padding:0px;margin:0px;}    
div{vertical-align:top;}    
img{max-width:100%;}    
html {-webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale;}    
body{overflow:auto!important; width:100%!important;}    
html, body{background-color:#e4e5e6;}    
html {position:relative; min-height:100%;}    
    
.card{border-radius:4px;}    
.card-header:first-child {border-radius:4px 4px 0px 0px;}    
    
/*Typekit*/    
html, body{font-family:'Roboto', sans-serif; font-weight:400; font-size:13px;}    
body{padding-top:52px;}    
    
p{font-family:'Roboto', sans-serif; color:#303030; font-weight:400; margin-bottom:1rem;}    
input, textarea, select{font-family:'Roboto', sans-serif;}    
    
h1,h2,h3,h4,h5,h6{font-family:'Roboto', sans-serif; font-weight:700;}    
h1{font-size:20px; color:#000000; margin-bottom:10px;}    
h2{font-size:30px;}    
h3{font-size:24px;}    
h4{font-size:18px;}    
h5{font-size:14px;}    
h6{font-size:12px;}    
    
.row {margin-right:-8px; margin-left:-8px;}    
.col, .col-1, .col-10, .col-11, .col-12, .col-2, .col-3, .col-4, .col-5, 
.col-6, .col-7, .col-8, .col-9, .col-auto, .col-lg, .col-lg-1, .col-lg-10, 
.col-lg-11, .col-lg-12, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, 
.col-lg-7, .col-lg-8, .col-lg-9, .col-lg-auto, .col-md, .col-md-1, .col-md-10, 
.col-md-11, .col-md-12, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, 
.col-md-7, .col-md-8, .col-md-9, .col-md-auto, .col-sm, .col-sm-1, .col-sm-10, 
.col-sm-11, .col-sm-12, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, 
.col-sm-7, .col-sm-8, .col-sm-9, .col-sm-auto, .col-xl, .col-xl-1, .col-xl-10, 
.col-xl-11, .col-xl-12, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, 
.col-xl-7, .col-xl-8, .col-xl-9, .col-xl-auto {padding-right:8px; padding-left:8px;}    
    
.card-header{background-color:#f0f3f5; border-bottom:1px solid #c8ced3; 
font-size:13px; font-weight:600; color:#464646; 
text-transform:uppercase; padding:.75rem 8px;}       
    
.cnstr-record th{white-space:nowrap;padding:.45rem .2rem; font-size:13px; 
border-bottom-width:0px!important;}    
.cnstr-record thead{background:#f0f3f5;}    
    
.cnstr-record .form-control{font-size:13px; padding:0px 0rem 0px 0.2rem; 
height:calc(2rem + 2px);}    
.cnstr-record select.form-control{padding-left:.05rem;}    
.cnstr-record .table td, .cnstr-record .table th {vertical-align:middle;}    
.cnstr-record .table td{padding:.3rem;}    
.cnstr-record .table td h4{margin:0px;}    
    
.wp-50{width:50px;}    
.wp-60{width:60px;}    
.wp-70{width:70px;}    
.wp-80{width:80px;}    
.wp-90{width:90px;}    
.wp-100{width:100px;}    
.mw-auto{min-width:inherit;}    
.expand-row{width:100%; border:solid 1px #596269; display:inline-block; 
border-radius:3px; width:16px; height:16px; vertical-align:top; 
background:#596269; color:#ffffff!important;}    
.expand-row img{vertical-align:top; position:relative; top:2px;}    
.sub-table th{font-weight:400; font-size:12px;}    
.sub-table td{background:#efefef;}    
.no-bg td{background:inherit;}    
.mw-100{max-width:100%;}    
   
.activeTabColor{  
    color: #fff;  
    background-color: #000000;  
}   
.page-item:first-child .page-link {  
    margin-left: 0;  
    border-top-left-radius: .25rem;  
    border-bottom-left-radius: .25rem;  
}  
  
.pageColor{  
    position: relative;  
    display: block;  
    padding: .5rem .75rem;  
    margin-left: -1px;  
    line-height: 1.25;  
    color: white!important;  
    background-color: black!important;  
    border: 1px solid #dee2e6;  
}  
.notAllowed{  
    position: relative;  
    display: block;  
    padding: .5rem .75rem;  
    margin-left: -1px;  
    line-height: 1.25;  
    color: #007bff;  
    background-color: #fff;  
    border: 1px solid #dee2e6;  
    cursor: not-allowed;  
}  
.page-link {  
    position: relative;  
    display: block;  
    padding: .5rem .75rem;  
    margin-left: -1px;  
    line-height: 1.25;  
    color: #007bff;  
    background-color: #fff;  
    border: 1px solid #dee2e6;  
}   
}

步骤 8

最后,打开 pagination.service.ts 文件并添加服务以调用我们的 API。

import { Injectable } from '@angular/core';  
  
@Injectable()  
  
export class PaginationService {  
    //Pagination Variables  
  
    temppage: number = 0;  
    pageField = [];  
    exactPageList: any;  
  
    constructor() {  
    }  
  
    // On page load   
    pageOnLoad() {  
        if (this.temppage == 0) {  
  
            this.pageField = [];  
            for (var a = 0; a < this.exactPageList; a++) {  
                this.pageField[a] = this.temppage + 1;  
                this.temppage = this.temppage + 1;  
            }  
        }  
    }    
}

步骤 9

让我们在 api.service.ts 文件中添加以下代码

import { Injectable } from '@angular/core';  
import { HttpClient } from '@angular/common/http';  
import { Observable } from 'rxjs';  
  
@Injectable({  
  providedIn: 'root'  
})  
export class ApiService {  
    private url = "";  
  
    constructor(public http: HttpClient) {  
    }    
  
getAllCompanies(pageNo,pageSize,sortOrder): Observable<any> {  
    this.url = 'https://:59390/api/Pagination/getAllCompanies?pageNo=' + 
                pageNo+'&pageSize='+pageSize+'&sortOrder='+sortOrder;  
    return this.http.get(this.url);  
  }  
  
  getAllCompaniesCount(): Observable<any> {  
    this.url = 'https://:59390/api/Pagination/getAllCompaniesCount';  
    return this.http.get(this.url);  
  }  
} 

第 10 步

下一步也是最后一步是向项目中添加 app 模块文件。

import { BrowserModule } from '@angular/platform-browser';  
import { NgModule } from '@angular/core';  
  
import { AppComponent } from './app.component';  
import { ApiService } from './pagination/api.service';  
import { HttpClientModule } from '@angular/common/http';  
import { PaginationService } from './pagination/pagination.service';  
import { PaginationComponent } from './pagination/pagination.component';  
  
@NgModule({  
  declarations: [  
    AppComponent,  
    PaginationComponent  
  ],  
  imports: [  
    BrowserModule,  
    HttpClientModule  
  ],  
  providers: [ApiService,PaginationService],  
  bootstrap: [AppComponent]  
})  
export class AppModule { }  

第 11 步

现在是时候查看输出了,只需打开终端并键入“ng serve -o”以自动编译并在浏览器中打开。

加载我们的页面后,您可以看到如下所示的输出图像

在这里,总记录数为 33,基于此,我们的前端逻辑将计算页数,即每页显示 5 条记录(可更改),因此直到第 6 页,每页有 5 条记录,这意味着现在只剩下 3 条记录,它们将出现在最后一页,即第 7 页。

Server Side Pagination Using ASP.NET Core And Angular 8

第 2 页:要显示的记录总数为 5

Server Side Pagination Using ASP.NET Core And Angular 8

在最后一页,只显示 3 条记录。

Server Side Pagination Using ASP.NET Core And Angular 8

通过这一步,我们已成功完成了前端、Web API 和后端编码。

结论

在本文中,我试图解释如何使用 Angular 8 和 ASP.NET 进行服务器端分页,获取记录并以分页方式显示它们。

这是服务器端分页的第一部分。

在我下一篇文章或第二部分中,我们将学习如何添加上一步下一步按钮,此外,我们将手动设置每页的记录总数。

我只是一个学习者,渴望学习新事物,不仅仅是技术方面,而是所有方面。

“永不停止学习,因为生活永不停止教导” .....作者:释迦牟尼。

最后,请不要忘记就本文提供您宝贵的反馈/评论/问题。如果您喜欢并理解本文,请告诉我,我该如何改进它。

历史

  • 2020 年 1 月 9 日:初始版本
© . All rights reserved.