第 6 章 高級查詢和日志
6.1 分頁
在 EF Core 中,數(shù)據(jù)的查詢通過集成語言查詢(LINQ)實現(xiàn),它支持強類型,支持對 DbContext 派生類的 DbSet 類型成員進(jìn)行訪問,DbSet 類實現(xiàn)了 IQueryable 和 IEnumerable 接口,LINQ 形式的查詢會通過數(shù)據(jù)庫提供程序轉(zhuǎn)換為數(shù)據(jù)庫查詢語言,并最終返回實體集合
接下來,在 Library.API 項目中實現(xiàn)分頁功能
添加一個 AuthorResourceParameters 類
namespace Library.API.Helpers
{
public class AuthorResourceParameters
{
public const int MaxPageSize = 50;
private int _pageSize = 10;
public int PageNumber { get; set; } = 1;
public int PageSize
{
get { return _pageSize; }
set
{
_pageSize = (value > MaxPageSize) ? MaxPageSize : value;
}
}
}
}
修改 GetAuthorsAsync 方法實現(xiàn)分頁
[HttpGet]
public async Task<ActionResult<List<AuthorDto>>> GetAuthorsAsync([FromQuery] AuthorResourceParameters parameters)
{
var authors = (await RepositoryWrapper.Author.GetAllAsync())
.Skip(parameters.PageSize * (parameters.PageNumber - 1))
.Take(parameters.PageSize)
.OrderBy(author => author.Name);
var authorDtoList = Mapper.Map<IEnumerable<AuthorDto>>(authors);
return authorDtoList.ToList();
}
完成之后可以請求 URL: ??http://localhost:5001/api/author?pageNumber=2&pageSize=3??
添加分頁元數(shù)據(jù)
首先創(chuàng)建一個分頁列表類
namespace Library.API.Helpers
{
public class PagedList<T> : List<T>
{
public int CurrentPage { get; private set; }
public int TotalPages { get; private set; }
public int PageSize { get; private set; }
public int TotalCount { get; private set; }
public bool HasPrevious => CurrentPage > 1;
public bool HasNext => CurrentPage < TotalPages;
public PagedList(List<T> items, int totalCount, int pageNumber, int pageSize)
{
TotalCount = totalCount;
CurrentPage = pageNumber;
PageSize = pageSize;
TotalPages = (int) Math.Ceiling((double) totalCount / pageSize);
AddRange(items);
}
}
}
在 IAuthorRepository 添加一個方法
Task<PagedList<Author>> GetAllAsync(AuthorResourceParameters parameters);
在 AuthorRepository 添加實現(xiàn)方法
public async Task<PagedList<Author>> GetAllAsync(AuthorResourceParameters parameters)
{
IQueryable<Author> queryableAuthors = DbContext.Set<Author>();
var totalCount = queryableAuthors.Count();
var items = queryableAuthors.Skip((parameters.PageNumber - 1) * parameters.PageSize)
.Take(parameters.PageSize).ToList();
return new PagedList<Author>(items, totalCount, parameters.PageNumber, parameters.PageSize);
}
為了使創(chuàng)建 PagedList 的邏輯具有通用性,可以在 PagedList 類中添加一個靜態(tài)方法 CreateAsync
public static async Task<PagedList<T>> CreateAsync(IQueryable<T> source, int pageNumber, int pageSize)
{
var totalCount = source.Count();
var items = source.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToList();
var list = new PagedList<T>(items, totalCount, pageNumber, pageSize);
return await Task.FromResult(list);
}
在 GetAllAsync 中使用
public Task<PagedList<Author>> GetAllAsync(AuthorResourceParameters parameters)
{
IQueryable<Author> queryableAuthors = DbContext.Set<Author>();
//var totalCount = queryableAuthors.Count();
//var items = queryableAuthors.Skip((parameters.PageNumber - 1) * parameters.PageSize)
// .Take(parameters.PageSize).ToList();
//return new PagedList<Author>(items, totalCount, parameters.PageNumber, parameters.PageSize);
return PagedList<Author>.CreateAsync(queryableAuthors, parameters.PageNumber, parameters.PageSize);
}
接下來,在 AuthorController 中重構(gòu) GetAuthorsAsync 代碼
[HttpGet(Name = nameof(GetAuthorsAsync))]
public async Task<ActionResult<List<AuthorDto>>> GetAuthorsAsync([FromQuery] AuthorResourceParameters parameters)
{
var pagedList = await RepositoryWrapper.Author.GetAllAsync(parameters);
var paginationMetedata = new
{
totalCount = pagedList.TotalCount,
pageSize = pagedList.PageSize,
currentPage = pagedList.CurrentPage,
totalPages = pagedList.TotalPages,
previousePageLink = pagedList.HasPrevious
? Url.Link(nameof(GetAuthorsAsync), new
{
pageNumber = pagedList.CurrentPage - 1,
pageSize = pagedList.PageSize
})
: null,
nextPageLink = pagedList.HasNext
? Url.Link(nameof(GetAuthorsAsync), new
{
pageNumber = pagedList.CurrentPage + 1,
pageSize = pagedList.PageSize
})
: null
};
Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(paginationMetedata));
//var authors = (await RepositoryWrapper.Author.GetAllAsync())
// .Skip(parameters.PageSize * (parameters.PageNumber - 1))
// .Take(parameters.PageSize)
// .OrderBy(author => author.Name);
var authorDtoList = Mapper.Map<IEnumerable<AuthorDto>>(pagedList);
return authorDtoList.ToList();
}
以 Get 方法請求 URL 后,服務(wù)器不僅返回所請求的資源,并且在響應(yīng)的消息頭中包含了分頁元數(shù)據(jù),可以通過 previousePageLink,nextPageLink 的 URL 值直接訪問上一頁以及下一頁數(shù)據(jù)
6.2 過濾和搜索
過濾,是對資源的一個或多個屬性與指定的參數(shù)值進(jìn)行匹配并篩選
通過出生地過濾作者,首先在 AuthorResourceParameters 中添加 BirthPlace 屬性
public string BirthPlace { get; set; }
然后,修改 AuthorRepository 的 GetAllAsync 方法
if (!string.IsNullOrWhiteSpace(parameters.BirthPlace))
{
queryableAuthors = queryableAuthors.Where(m => m.BirthPlace.ToLower() == parameters.BirthPlace);
}
接著,修改 AuthorController 的 GetAuthorsAsync 方法中生成分頁數(shù)據(jù)的代碼,添加過濾信息
previousePageLink = pagedList.HasPrevious
? Url.Link(nameof(GetAuthorsAsync), new
{
pageNumber = pagedList.CurrentPage - 1,
pageSize = pagedList.PageSize,
birthPlace = parameters.BirthPlace
})
: null,
nextPageLink = pagedList.HasNext
? Url.Link(nameof(GetAuthorsAsync), new
{
pageNumber = pagedList.CurrentPage + 1,
pageSize = pagedList.PageSize,
birthPlace = parameters.BirthPlace
})
: null
完成之后可以請求 URL: ??https://localhost:5001/api/authors?birthplace=beijing&pagesize=2??
這樣可以看到下一頁的 URL 中不僅包含分頁參數(shù),也包含過濾參數(shù)
搜索功能的實現(xiàn)方式與過濾一樣
首先在 AuthorResourceParameters 中添加 SearchQuery 屬性
public string SearchQuery { get; set; }
然后,修改 AuthorRepository 的 GetAllAsync 方法
if (!string.IsNullOrWhiteSpace(parameters.SearchQuery))
{
queryableAuthors = queryableAuthors.Where(m =>
m.BirthPlace.ToLower().Contains(parameters.SearchQuery.ToLower()) ||
m.Name.ToLower().Contains(parameters.SearchQuery.ToLower()));
}
接著,修改 AuthorController 的 GetAuthorsAsync 方法中生成分頁數(shù)據(jù)的代碼,添加過濾信息
previousePageLink = pagedList.HasPrevious
? Url.Link(nameof(GetAuthorsAsync), new
{
pageNumber = pagedList.CurrentPage - 1,
pageSize = pagedList.PageSize,
birthPlace = parameters.BirthPlace,
searchQuery = parameters.SearchQuery
})
: null,
nextPageLink = pagedList.HasNext
? Url.Link(nameof(GetAuthorsAsync), new
{
pageNumber = pagedList.CurrentPage + 1,
pageSize = pagedList.PageSize,
birthPlace = parameters.BirthPlace,
searchQuery = parameters.SearchQuery
})
: null
完成之后可以請求 URL: ??https://localhost:5001/api/authors?searchQuery=author&birthplace=beijing&pagesize=2??
這樣可以看到下一頁的 URL 中不僅包含分頁參數(shù),也包含過濾參數(shù)和查詢參數(shù)
本文摘自 :https://blog.51cto.com/u