用CQRS // C#在干净体系结构中的分页
几个星期以来,我一直在学习CQRS的清洁体系结构。我有一个有关良好实践以及如何实施更好的事情以使代码更具性能的问题。
问题涉及分页以及如何很好地实施它。据我了解,最好的方法是在从数据库中获取过程中分解结果,以免从DB获取所有记录,然后开始在UI层上进行划入。
我将paginedlist(Pagenumber,TotalPages,List等)和RequestParams类中放置在应用程序层中。我的处理程序看起来像这样:
public async Task < PaginatedList < TransactionInListViewModel >> Handle(GetTransactionsByBudgetIdQuery request,
CancellationToken cancellationToken) {
var userId = _userService.GetUserId;
var transactions = await _transactionRepository.GetTransactionsByBudgetIdAsync(
userId,
request.BudgetId,
request.PageNumber,
request.PageSize);
var transactionDto = _mapper.Map < List < TransactionInListViewModel >> (transactions.Items);
var result = new PaginatedList < TransactionInListViewModel > (
transactionDto,
transactions.TotalCount,
transactions.PageNumber,
transactions.PageSize);
return result;
}
方法向存储库询问用户本人创建的记录,从带有分页参数的特定篮子。
在存储库中,我有简单的请求使用这些参数和存储库返回的事务列表(IEnumerable)。
然后,该处理程序必须映射记录并返回分页结果。这里开始了问题,一切看起来都很完美,直到我意识到诸如TotalCount之类的参数以及与之相关的所有内容(例如Haspreviousepage HasnextPage)的行为就像我只问一页,这就是所有内容 - 总计是PageSize的量其余的只是显示错误的结果:)
我正试图找到解决方案,但我发现它是否仍然遵循干净的体系结构规则,还是我开始弄乱所有内容。我在基础架构层中重新分配了存储库类:
public async Task < PaginatedList < Transaction >> GetTransactionsByBudgetIdAsync(int userId, int budgetId, int pageNumber, int pageSize) {
var baseQuery = await _dbContext
.Transactions
.Where(t => t.CreatedById == userId)
.Where(t => t.BudgetId == budgetId)
.OrderByDescending(t => t.TransactionDate)
.ToListAsync();
var count = baseQuery.Count();
var transactions = baseQuery
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.ToList();
return new PaginatedList < Transaction > (transactions, count, pageNumber, pageSize);
}
正如我所说,现在整体结果看起来不错,但是对我来说,它看起来很混乱,我认为它不遵循CA规则。如果我在应用程序层中的Paginedlist类中,我应该在TransActionRopository(基础架构层中的)中使用它以返回带有完美计数数字的PaginedResult,然后将结果映射到处理程序中并再次将其绘制为pagine?
感谢所有回复!
For few weeks I've been learning Clean Architecture with CQRS. I've got a question about good practices and how to implement something better to make code more performant.
Question concerns pagination and how to implement it well. As I understand the best way is to paginate result during fetching from DB to not get all records from DB and then start paginating on UI layer.
I've put PaginatedList(pagenumber, totalpages, List etc.) and RequestParams classes in Application Layer. My handler looks like this:
public async Task < PaginatedList < TransactionInListViewModel >> Handle(GetTransactionsByBudgetIdQuery request,
CancellationToken cancellationToken) {
var userId = _userService.GetUserId;
var transactions = await _transactionRepository.GetTransactionsByBudgetIdAsync(
userId,
request.BudgetId,
request.PageNumber,
request.PageSize);
var transactionDto = _mapper.Map < List < TransactionInListViewModel >> (transactions.Items);
var result = new PaginatedList < TransactionInListViewModel > (
transactionDto,
transactions.TotalCount,
transactions.PageNumber,
transactions.PageSize);
return result;
}
Method asks repository for record created by user himself, from specific basket with pagination parameters.
In repository I had simple request to db with those parameters and repository returned Transaction List (IEnumerable).
Then this handler had to map the record and return paginated result. Here started the problem, everything looked perfect until I realized that parameters like TotalCount and everything connected to it (like HasPreviousePage HasNextPage) behave like I only have asked about one page and thats all - TotalCount was the amount of PageSize, and except PageNumber and PageSize the rest just show false results :)
I was trying to find the solution and I found it, but I dont know if it still follows Clean Architecture rules or I just started messing everything up. I refactored Repository class in Infrastructure layer to this:
public async Task < PaginatedList < Transaction >> GetTransactionsByBudgetIdAsync(int userId, int budgetId, int pageNumber, int pageSize) {
var baseQuery = await _dbContext
.Transactions
.Where(t => t.CreatedById == userId)
.Where(t => t.BudgetId == budgetId)
.OrderByDescending(t => t.TransactionDate)
.ToListAsync();
var count = baseQuery.Count();
var transactions = baseQuery
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.ToList();
return new PaginatedList < Transaction > (transactions, count, pageNumber, pageSize);
}
As I said, now whole results looks fine, but for me it looks messy and I dont think It follows CA rules. If I have PaginatedList class in Application Layer should I use it in TransactionRepository (which is in Infrastructure layer) to return PaginatedResult with perfectly counted numbers and then Map the result in Handler and Paginate it again?
Thanks for all responses!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论