评论本来是要放到标签里面去讲的,但是因为上一章东西有点多了,我就没放进去,这一章单独拿出来,内容不多大家自己写写就可以,也算是对前面讲解的一个小练习吧。

相关注释我也加在代码上面了,大家看看代码都可以理解。

  1. public interface ICommentRepository : IBasicRepository<Comment, Guid>
  2. {
  3. /// <summary>
  4. /// 根据文章Id 获取评论
  5. /// </summary>
  6. /// <param name="postId"></param>
  7. /// <param name="cancellationToken"></param>
  8. /// <returns></returns>
  9. Task<List<Comment>> GetListOfPostAsync(Guid postId, CancellationToken cancellationToken = default);
  10. /// <summary>
  11. /// 根据文章Id 获取评论数量
  12. /// </summary>
  13. /// <param name="postId"></param>
  14. /// <param name="cancellationToken"></param>
  15. /// <returns></returns>
  16. Task<int> GetCommentCountOfPostAsync(Guid postId, CancellationToken cancellationToken = default);
  17. /// <summary>
  18. /// 根据评论Id 下面的子获取评论
  19. /// </summary>
  20. /// <param name="id"></param>
  21. /// <param name="cancellationToken"></param>
  22. /// <returns></returns>
  23. Task<List<Comment>> GetRepliesOfComment(Guid id, CancellationToken cancellationToken = default);
  24. Task DeleteOfPost(Guid id, CancellationToken cancellationToken = default);
  25. }
  26. public class EfCoreCommentRepository:EfCoreRepository<CoreDbContext, Comment, Guid>,ICommentRepository
  27. {
  28. public EfCoreCommentRepository(IDbContextProvider<CoreDbContext> dbContextProvider) : base(dbContextProvider)
  29. {
  30. }
  31. public async Task<List<Comment>> GetListOfPostAsync(Guid postId, CancellationToken cancellationToken = default)
  32. {
  33. return await (await GetDbSetAsync())
  34. .Where(a => a.PostId == postId)
  35. .OrderBy(a => a.CreationTime)
  36. .ToListAsync(GetCancellationToken(cancellationToken));
  37. }
  38. public async Task<int> GetCommentCountOfPostAsync(Guid postId, CancellationToken cancellationToken = default)
  39. {
  40. return await (await GetDbSetAsync())
  41. .CountAsync(a => a.PostId == postId, GetCancellationToken(cancellationToken));
  42. }
  43. public async Task<List<Comment>> GetRepliesOfComment(Guid id, CancellationToken cancellationToken = default)
  44. {
  45. return await (await GetDbSetAsync())
  46. .Where(a => a.RepliedCommentId == id).ToListAsync(GetCancellationToken(cancellationToken));
  47. }
  48. public async Task DeleteOfPost(Guid id, CancellationToken cancellationToken = default)
  49. {
  50. var recordsToDelete = await (await GetDbSetAsync()).Where(pt => pt.PostId == id).ToListAsync(GetCancellationToken(cancellationToken));
  51. (await GetDbSetAsync()).RemoveRange(recordsToDelete);
  52. }
  53. }
  1. public interface ICommentAppService : IApplicationService
  2. {
  3. Task<List<CommentWithRepliesDto>> GetHierarchicalListOfPostAsync(Guid postId);
  4. Task<CommentWithDetailsDto> CreateAsync(CreateCommentDto input);
  5. Task<CommentWithDetailsDto> UpdateAsync(Guid id, UpdateCommentDto input);
  6. Task DeleteAsync(Guid id);
  7. }
  8. public class CommentWithRepliesDto
  9. {
  10. public CommentWithDetailsDto Comment { get; set; }
  11. public List<CommentWithDetailsDto> Replies { get; set; } = new List<CommentWithDetailsDto>();
  12. }
  13. public class CommentWithDetailsDto : FullAuditedEntityDto<Guid>
  14. {
  15. public Guid? RepliedCommentId { get; set; }
  16. public string Text { get; set; }
  17. public BlogUserDto Writer { get; set; }
  18. }
  19. public class CreateCommentDto
  20. {
  21. public Guid? RepliedCommentId { get; set; }
  22. public Guid PostId { get; set; }
  23. [Required]
  24. public string Text { get; set; }
  25. }
  26. public class UpdateCommentDto
  27. {
  28. [Required]
  29. public string Text { get; set; }
  30. }
  1. public class CommentAppService : CoreAppService, ICommentAppService
  2. {
  3. private IUserLookupService<IdentityUser> UserLookupService { get; }
  4. private readonly ICommentRepository _commentRepository;
  5. private readonly IGuidGenerator _guidGenerator;
  6. public CommentAppService(ICommentRepository commentRepository, IGuidGenerator guidGenerator, IUserLookupService<IdentityUser> userLookupService)
  7. {
  8. _commentRepository = commentRepository;
  9. _guidGenerator = guidGenerator;
  10. UserLookupService = userLookupService;
  11. }
  12. public async Task<List<CommentWithRepliesDto>> GetHierarchicalListOfPostAsync(Guid postId)
  13. {
  14. // 获取评论数据
  15. var comments = await GetListOfPostAsync(postId);
  16. #region 对评论的作者进行赋值
  17. var userDictionary = new Dictionary<Guid, BlogUserDto>();
  18. foreach (var commentDto in comments)
  19. {
  20. if (commentDto.CreatorId.HasValue)
  21. {
  22. var creatorUser = await UserLookupService.FindByIdAsync(commentDto.CreatorId.Value);
  23. if (creatorUser != null && !userDictionary.ContainsKey(creatorUser.Id))
  24. {
  25. userDictionary.Add(creatorUser.Id, ObjectMapper.Map<IdentityUser, BlogUserDto>(creatorUser));
  26. }
  27. }
  28. }
  29. foreach (var commentDto in comments)
  30. {
  31. if (commentDto.CreatorId.HasValue && userDictionary.ContainsKey((Guid)commentDto.CreatorId))
  32. {
  33. commentDto.Writer = userDictionary[(Guid)commentDto.CreatorId];
  34. }
  35. }
  36. #endregion
  37. var hierarchicalComments = new List<CommentWithRepliesDto>();
  38. #region 包装评论数据格式
  39. // 评论包装成2级(ps:前面的查询根据时间排序,这里不要担心子集在父级前面)
  40. foreach (var commentDto in comments)
  41. {
  42. var parent = hierarchicalComments.Find(c => c.Comment.Id == commentDto.RepliedCommentId);
  43. if (parent != null)
  44. {
  45. parent.Replies.Add(commentDto);
  46. }
  47. else
  48. {
  49. hierarchicalComments.Add(new CommentWithRepliesDto() { Comment = commentDto });
  50. }
  51. }
  52. hierarchicalComments = hierarchicalComments.OrderByDescending(c => c.Comment.CreationTime).ToList();
  53. #endregion
  54. return hierarchicalComments;
  55. }
  56. public async Task<CommentWithDetailsDto> CreateAsync(CreateCommentDto input)
  57. {
  58. // 也可以使用这种方式(这里只是介绍用法) GuidGenerator.Create()
  59. var comment = new Comment(_guidGenerator.Create(), input.PostId, input.RepliedCommentId, input.Text);
  60. comment = await _commentRepository.InsertAsync(comment);
  61. await CurrentUnitOfWork.SaveChangesAsync();
  62. return ObjectMapper.Map<Comment, CommentWithDetailsDto>(comment);
  63. }
  64. public async Task<CommentWithDetailsDto> UpdateAsync(Guid id, UpdateCommentDto input)
  65. {
  66. var comment = await _commentRepository.GetAsync(id);
  67. comment.SetText(input.Text);
  68. comment = await _commentRepository.UpdateAsync(comment);
  69. return ObjectMapper.Map<Comment, CommentWithDetailsDto>(comment);
  70. }
  71. public async Task DeleteAsync(Guid id)
  72. {
  73. await _commentRepository.DeleteAsync(id);
  74. var replies = await _commentRepository.GetRepliesOfComment(id);
  75. foreach (var reply in replies)
  76. {
  77. await _commentRepository.DeleteAsync(reply.Id);
  78. }
  79. }
  80. private async Task<List<CommentWithDetailsDto>> GetListOfPostAsync(Guid postId)
  81. {
  82. var comments = await _commentRepository.GetListOfPostAsync(postId);
  83. return new List<CommentWithDetailsDto>(
  84. ObjectMapper.Map<List<Comment>, List<CommentWithDetailsDto>>(comments));
  85. }
  86. }
  1. CreateMap<Comment, CommentWithDetailsDto>().Ignore(x => x.Writer);

说明:

  • 1.整个评论的实现非常简单,我们只是实现了一个2层的嵌套。
  • 2.下一章我们讲授权和策略大家应该会比较喜欢,加油

联系作者:加群:867095512 @MrChuJiu

公众号

版权声明:本文为MrChuJiu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/MrChuJiu/p/15307159.html