Xây dựng phân trang hiệu quả trong Asp.Net
Introduction
Bài viết này sẽ giải thích tại sao sử dụng phân trang cho chỉ các records được yêu cầu, và hiển thị chúng dưới dạng paging và có reference tới tổng số records.
Background
Rất có thể bạn đã gặp phải vấn đề mà bạn cần liệt kê một vài record từ nguồn dữ liệu có chứa vài nghìn hoặc nhiều hơn records sau đó nhận thấy rằng phân trang là một yếu tố quan trọng để cải thiện hiệu suất trang web. Bắt đầu từ việc lọc dữ liệu đến chọn các bản ghi liên quan từ cơ sở dữ liệu đến hiển thị phân trang, có một vài bước quan trọng nhưng cần xem xét để xây dựng một hệ thống phân trang đáng tin cậy.
Creating the project
Ta sẽ để mặc định ASP.Net Core 2.2 project template sử dụng VS2019,
Trước khi đào sâu tới phân trang ta cần tạo datasource cho các records test. Datasource cần chứa nhiều records vậy sẽ thấy được lợi ích thực sự của việc phân trang. Theo thứ tự trước hết focus vào topic phân trang. Ta sẽ có 1 list items (CultureInfo) cái đã có sẵn trong famework.
Open
Pages/Index.cshtml.cs and add the data source as below:public class IndexModel : PageModel
{
public CultureInfo[] CulturesList { get; set; }
private CultureInfo[] Cultures { get; set; }
public IndexModel()
{
//this will act as the main data source for our project
Cultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
}
public void OnGet()
{
CulturesList = Cultures;
}
}
Open
Pages/Index.cshtml and add the below code to display the cultures list:<table class="table table-striped">
<thead>
<tr>
<th>LCID</th>
<th>English Name</th>
<th>Native Name</th>
<th>Culture types</th>
</tr>
</thead>
<tbody>
@foreach (var c in Model.CulturesList)
{
<tr>
<td>@c.LCID</td>
<td>@c.EnglishName</td>
<td>@c.NativeName</td>
<td>@c.CultureTypes</td>
</tr>
}
</tbody>
</table>
Run the app to see the first results;
Handling paging on the backend
Như bạn đã biết việc gửi toàn bộ records tới view là cách làm không hiệu quả trong lập trình, vì thế ta sẽ limit số lượng records được select và sẽ gửi tới view một số lượng nhỏ bản ghi hơn. Theo các đơn giản ta cần 2 biến cho phân trang.
- Page number : a variable to indicate the requested page number
- Page size : a variable to indicate the total numbers of records that should be selected at once
later we will add more variables for filtering as well.
Back to
Pages/Index.cshtml.cs file, define the variables and modify OnGet, so our new IndexModel will look like below:public class IndexModel : PageModel
{
public IList<CultureInfo> CulturesList { get; set; }
private CultureInfo[] Cultures { get; set; }
//page number variable
[BindProperty(SupportsGet = true)]
public int P { get; set; } = 1;
//page size variable
[BindProperty(SupportsGet = true)]
public int S { get; set; } = 10;
public IndexModel()
{
//this will act as the main data source for our project
Cultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
}
public void OnGet()
{
CulturesList = Cultures
//make sure to order items before paging
.OrderBy(x=>x.EnglishName)
//skip items before current page
.Skip((P-1)*S)
//take only 10 (page size) items
.Take(S)
//call ToList() at the end to execute the query and return the result set
.ToList();
}
}
Run the app, you will see first 10 records only,
Improving search logic
- Ta sử dụng 1 keyword trong việc search. Ta có thể cải tiến query bằng việc phân tách keywords và xóa bỏ khoảng trắng và các từ trùng lặp như sau:
var _keyWords = Q.Split(new[] { ' ', ',', ':' }, StringSplitOptions.RemoveEmptyEntries).Distinct();
- Khi sử dụng hệ cơ sở dự liệu MSSqlDb và thực hiện việc search trong nullable fields ta có thể nhận error khi field bị null, để tránh null field ta có thể thêm điều kiện check null cho search logic.
var query = Cultures
//search in EnglishName and NativeName
.Where(x => _keyWords.Any(kw =>
(x.EnglishName!=null && x.EnglishName.Contains(kw, StringComparison.OrdinalIgnoreCase)) ||
(x.NativeName != null && x.NativeName.Contains(kw, StringComparison.OrdinalIgnoreCase))))
- Thực tế có thể cải thiện thêm hiệu suất bằng cách sử dụng
AsNoTracking() khi tìm kiếm database, vì thế famework sẽ không giữ lại các entites đã chọn và sẽ giải phóng bộ nhớ.
Nhận xét
Đăng nhận xét