浏览代码

留言评论分类菜单平行查询建树

懒得勤快 3 年之前
父节点
当前提交
8ee2820d17

+ 2 - 2
src/Masuit.MyBlogs.Core/Controllers/CategoryController.cs

@@ -6,8 +6,8 @@ using Masuit.MyBlogs.Core.Models.DTO;
 using Masuit.MyBlogs.Core.Models.Entity;
 using Masuit.MyBlogs.Core.Models.Enum;
 using Masuit.Tools.AspNetCore.ModelBinder;
+using Masuit.Tools.Models;
 using Microsoft.AspNetCore.Mvc;
-using Microsoft.EntityFrameworkCore;
 
 namespace Masuit.MyBlogs.Core.Controllers
 {
@@ -27,7 +27,7 @@ namespace Masuit.MyBlogs.Core.Controllers
         /// <returns></returns>
         public ActionResult GetCategories()
         {
-            var list = CategoryService.GetQuery(c => c.Status == Status.Available && c.ParentId == null, c => c.Name).Include(c => c.Children).ThenInclude(c => c.Children).ToList();
+            var list = CategoryService.GetQueryNoTracking(c => c.Status == Status.Available, c => c.Name).ToList().ToTree(c => c.Id, c => c.ParentId);
             return ResultData(list.Mapper<List<CategoryDto>>());
         }
 

+ 15 - 7
src/Masuit.MyBlogs.Core/Controllers/CommentController.cs

@@ -20,6 +20,8 @@ using Microsoft.Net.Http.Headers;
 using System.ComponentModel.DataAnnotations;
 using System.Text;
 using System.Text.RegularExpressions;
+using Masuit.Tools.Systems;
+using Microsoft.EntityFrameworkCore;
 using SameSiteMode = Microsoft.AspNetCore.Http.SameSiteMode;
 
 namespace Masuit.MyBlogs.Core.Controllers
@@ -30,8 +32,11 @@ namespace Masuit.MyBlogs.Core.Controllers
     public class CommentController : BaseController
     {
         public ICommentService CommentService { get; set; }
+
         public IPostService PostService { get; set; }
+
         public IWebHostEnvironment HostEnvironment { get; set; }
+
         public ICacheManager<int> CommentFeq { get; set; }
 
         /// <summary>
@@ -62,7 +67,6 @@ namespace Masuit.MyBlogs.Core.Controllers
             }
 
             Post post = await PostService.GetByIdAsync(cmd.PostId) ?? throw new NotFoundException("评论失败,文章未找到");
-            CheckPermission(post);
             if (post.DisableComment)
             {
                 return ResultData(null, false, "本文已禁用评论功能,不允许任何人回复!");
@@ -76,6 +80,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             }
 
             var comment = cmd.Mapper<Comment>();
+            comment.GroupTag = cmd.ParentId > 0 ? CommentService.GetQuery(c => c.Id == cmd.ParentId).Select(c => c.GroupTag).FirstOrDefault() : SnowFlake.NewId;
             if (cmd.Email == post.Email || cmd.Email == post.ModifierEmail || Regex.Match(cmd.NickName + cmd.Content, CommonHelper.ModRegex).Length <= 0)
             {
                 comment.Status = Status.Published;
@@ -141,6 +146,7 @@ namespace Masuit.MyBlogs.Core.Controllers
                 {
                     emails.Add(post.Email);
                     emails.Add(post.ModifierEmail);
+
                     //新评论,只通知博主和楼主
                     foreach (var s in emails)
                     {
@@ -208,8 +214,8 @@ namespace Masuit.MyBlogs.Core.Controllers
             if (cid != 0)
             {
                 var comment = await CommentService.GetByIdAsync(cid) ?? throw new NotFoundException("评论未找到");
-                var single = new[] { comment.Root() };
-                foreach (var c in single.Flatten())
+                var layer = CommentService.GetQueryNoTracking(c => c.GroupTag == comment.GroupTag).ToList();
+                foreach (var c in layer)
                 {
                     c.CommentDate = c.CommentDate.ToTimeZone(HttpContext.Session.Get<string>(SessionKey.TimeZone));
                     c.IsAuthor = c.Email == comment.Post.Email || c.Email == comment.Post.ModifierEmail;
@@ -227,7 +233,7 @@ namespace Masuit.MyBlogs.Core.Controllers
                     parentTotal = 1,
                     page,
                     size,
-                    rows = single.Mapper<IList<CommentViewModel>>()
+                    rows = layer.ToTree(c => c.Id, c => c.ParentId).Mapper<IList<CommentViewModel>>()
                 });
             }
 
@@ -237,7 +243,9 @@ namespace Masuit.MyBlogs.Core.Controllers
                 return ResultData(null, false, "没有评论");
             }
             int total = parent.TotalCount; //总条数,用于前台分页
-            parent.Data.Flatten().ForEach(c =>
+            var tags = parent.Data.Select(c => c.GroupTag).ToArray();
+            var comments = CommentService.GetQuery(c => tags.Contains(c.GroupTag)).Include(c => c.Post).AsNoTracking().ToList();
+            comments.ForEach(c =>
             {
                 c.CommentDate = c.CommentDate.ToTimeZone(HttpContext.Session.Get<string>(SessionKey.TimeZone));
                 c.IsAuthor = c.Email == c.Post.Email || c.Email == c.Post.ModifierEmail;
@@ -256,7 +264,7 @@ namespace Masuit.MyBlogs.Core.Controllers
                     parentTotal = total,
                     page,
                     size,
-                    rows = parent.Data.Mapper<IList<CommentViewModel>>()
+                    rows = comments.OrderByDescending(c => c.CommentDate).ToTree(c => c.Id, c => c.ParentId).Mapper<IList<CommentViewModel>>()
                 });
             }
 
@@ -328,4 +336,4 @@ namespace Masuit.MyBlogs.Core.Controllers
             return Ok(pages);
         }
     }
-}
+}

+ 4 - 2
src/Masuit.MyBlogs.Core/Controllers/MenuController.cs

@@ -5,6 +5,7 @@ using Masuit.MyBlogs.Core.Models.DTO;
 using Masuit.MyBlogs.Core.Models.Entity;
 using Masuit.MyBlogs.Core.Models.Enum;
 using Masuit.Tools.AspNetCore.ModelBinder;
+using Masuit.Tools.Models;
 using Masuit.Tools.Systems;
 using Microsoft.AspNetCore.Mvc;
 
@@ -26,7 +27,7 @@ namespace Masuit.MyBlogs.Core.Controllers
         /// <returns></returns>
         public ActionResult GetMenus()
         {
-            var menus = MenuService.GetQuery(m => m.ParentId == null, m => m.Sort).ThenBy(m => m.Sort).ToList();
+            var menus = MenuService.GetAllNoTracking(m => m.Sort).ToList().ToTree(m => m.Id, m => m.ParentId);
             return ResultData(Mapper.Map<List<MenuDto>>(menus));
         }
 
@@ -34,6 +35,7 @@ namespace Masuit.MyBlogs.Core.Controllers
         /// 获取菜单类型
         /// </summary>
         /// <returns></returns>
+        [ResponseCache(Duration = 86400)]
         public ActionResult GetMenuType()
         {
             var array = Enum.GetValues(typeof(MenuType));
@@ -56,7 +58,7 @@ namespace Masuit.MyBlogs.Core.Controllers
         /// <returns></returns>
         public async Task<ActionResult> Delete(int id)
         {
-            var menus = MenuService.GetChildrenMenusByParentId(id);
+            var menus = MenuService[id].Flatten();
             bool b = await MenuService.DeleteEntitiesSavedAsync(menus) > 0;
             return ResultData(null, b, b ? "删除成功" : "删除失败");
         }

+ 11 - 7
src/Masuit.MyBlogs.Core/Controllers/MsgController.cs

@@ -21,6 +21,7 @@ using Microsoft.Net.Http.Headers;
 using System.ComponentModel.DataAnnotations;
 using System.Text;
 using System.Text.RegularExpressions;
+using Masuit.Tools.Systems;
 using SameSiteMode = Microsoft.AspNetCore.Http.SameSiteMode;
 
 namespace Masuit.MyBlogs.Core.Controllers
@@ -68,8 +69,8 @@ namespace Masuit.MyBlogs.Core.Controllers
             if (cid != 0)
             {
                 var message = await LeaveMessageService.GetByIdAsync(cid) ?? throw new NotFoundException("留言未找到");
-                var single = new[] { message.Root() };
-                foreach (var m in single.Flatten())
+                var layer = LeaveMessageService.GetQueryNoTracking(e => e.GroupTag == message.GroupTag).ToList();
+                foreach (var m in layer)
                 {
                     m.PostDate = m.PostDate.ToTimeZone(HttpContext.Session.Get<string>(SessionKey.TimeZone));
                     if (!CurrentUser.IsAdmin)
@@ -86,7 +87,7 @@ namespace Masuit.MyBlogs.Core.Controllers
                     parentTotal = 1,
                     page,
                     size,
-                    rows = single.Mapper<IList<LeaveMessageViewModel>>()
+                    rows = layer.ToTree(e => e.Id, e => e.ParentId).Mapper<IList<LeaveMessageViewModel>>()
                 });
             }
 
@@ -96,7 +97,9 @@ namespace Masuit.MyBlogs.Core.Controllers
                 return ResultData(null, false, "没有留言");
             }
             var total = parent.TotalCount;
-            parent.Data.Flatten().ForEach(m =>
+            var tags = parent.Data.Select(c => c.GroupTag).ToArray();
+            var messages = LeaveMessageService.GetQueryNoTracking(c => tags.Contains(c.GroupTag)).ToList();
+            messages.ForEach(m =>
             {
                 m.PostDate = m.PostDate.ToTimeZone(HttpContext.Session.Get<string>(SessionKey.TimeZone));
                 if (!CurrentUser.IsAdmin)
@@ -114,7 +117,7 @@ namespace Masuit.MyBlogs.Core.Controllers
                     parentTotal = total,
                     page,
                     size,
-                    rows = Mapper.Map<List<LeaveMessageViewModel>>(parent.Data)
+                    rows = messages.OrderByDescending(c => c.PostDate).ToTree(c => c.Id, c => c.ParentId).Mapper<IList<LeaveMessageViewModel>>()
                 });
             }
 
@@ -156,6 +159,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             }
 
             var msg = cmd.Mapper<LeaveMessage>();
+            msg.GroupTag = cmd.ParentId > 0 ? LeaveMessageService.GetQuery(c => c.Id == cmd.ParentId).Select(c => c.GroupTag).FirstOrDefault() : SnowFlake.NewId;
             if (Regex.Match(cmd.NickName + cmd.Content, CommonHelper.ModRegex).Length <= 0)
             {
                 msg.Status = Status.Published;
@@ -378,6 +382,6 @@ namespace Masuit.MyBlogs.Core.Controllers
             return ResultData(null, true, "站内消息清除成功!");
         }
 
-        #endregion
+        #endregion 站内消息
     }
-}
+}

+ 6 - 4
src/Masuit.MyBlogs.Core/Controllers/SubscribeController.cs

@@ -15,6 +15,8 @@ using Microsoft.Net.Http.Headers;
 using System.Linq.Expressions;
 using System.Text;
 using System.Text.RegularExpressions;
+using EFCoreSecondLevelCacheInterceptor;
+using Microsoft.EntityFrameworkCore;
 using WilderMinds.RssSyndication;
 
 namespace Masuit.MyBlogs.Core.Controllers
@@ -43,7 +45,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             var time = DateTime.Today.AddDays(-1);
             string scheme = Request.Scheme;
             var host = Request.Host;
-            var raw = PostService.GetQueryFromCache(PostBaseWhere().And(p => p.Rss && p.Status == Status.Published && p.ModifyDate >= time), p => p.ModifyDate, false).ToList();
+            var raw = PostService.GetQuery(PostBaseWhere().And(p => p.Rss && p.Status == Status.Published && p.ModifyDate >= time), p => p.ModifyDate, false).Include(p => p.Category).AsNoTracking().Cacheable().ToList();
             var data = await raw.SelectAsync(async p =>
             {
                 var summary = await p.Content.GetSummary(300, 50);
@@ -126,7 +128,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             var host = Request.Host;
             var category = await categoryService.GetByIdAsync(id) ?? throw new NotFoundException("分类未找到");
             var cids = category.Flatten().Select(c => c.Id).ToArray();
-            var raw = PostService.GetQueryFromCache(PostBaseWhere().And(p => p.Rss && cids.Contains(p.CategoryId) && p.Status == Status.Published && p.ModifyDate >= time), p => p.ModifyDate, false).ToList();
+            var raw = PostService.GetQuery(PostBaseWhere().And(p => p.Rss && cids.Contains(p.CategoryId) && p.Status == Status.Published && p.ModifyDate >= time), p => p.ModifyDate, false).Include(p => p.Category).AsNoTracking().Cacheable().ToList();
             var data = await raw.SelectAsync(async p =>
             {
                 var summary = await p.Content.GetSummary(300, 50);
@@ -183,7 +185,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             string scheme = Request.Scheme;
             var host = Request.Host;
             var seminar = await seminarService.GetByIdAsync(id) ?? throw new NotFoundException("专题未找到");
-            var raw = PostService.GetQueryFromCache(PostBaseWhere().And(p => p.Rss && p.Seminar.Any(s => s.Id == id) && p.Status == Status.Published && p.ModifyDate >= time), p => p.ModifyDate, false).ToList();
+            var raw = PostService.GetQuery(PostBaseWhere().And(p => p.Rss && p.Seminar.Any(s => s.Id == id) && p.Status == Status.Published && p.ModifyDate >= time), p => p.ModifyDate, false).Include(p => p.Category).AsNoTracking().Cacheable().ToList();
             var data = await raw.SelectAsync(async p =>
             {
                 var summary = await p.Content.GetSummary(300, 50);
@@ -250,7 +252,7 @@ namespace Masuit.MyBlogs.Core.Controllers
                 Body = summary,
                 Categories = new List<string>
                 {
-                    post.Category.Name
+                    post.Category.Path()
                 },
                 Link = new Uri(scheme + "://" + host + "/" + post.Id),
                 PublishDate = post.ModifyDate.ToTimeZone(HttpContext.Session.Get<string>(SessionKey.TimeZone)),

+ 2 - 1
src/Masuit.MyBlogs.Core/Infrastructure/DataContext.cs

@@ -1,5 +1,6 @@
 using Masuit.MyBlogs.Core.Models.Entity;
 using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Diagnostics;
 
 namespace Masuit.MyBlogs.Core.Infrastructure
 {
@@ -11,7 +12,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure
 
         protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
         {
-            optionsBuilder.EnableDetailedErrors().UseLazyLoadingProxies().UseQueryTrackingBehavior(QueryTrackingBehavior.TrackAll);
+            optionsBuilder.EnableDetailedErrors().UseLazyLoadingProxies().UseQueryTrackingBehavior(QueryTrackingBehavior.TrackAll).ConfigureWarnings(builder => builder.Ignore(CoreEventId.DetachedLazyLoadingWarning));
         }
 
         protected override void OnModelCreating(ModelBuilder modelBuilder)

+ 21 - 21
src/Masuit.MyBlogs.Core/Infrastructure/Repository/BaseRepository.cs

@@ -46,7 +46,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns></returns>
         public virtual IEnumerable<T> GetAllFromCache()
         {
-            return DataContext.Set<T>().Cacheable().AsEnumerable();
+            return DataContext.Set<T>().AsNoTracking().Cacheable().AsEnumerable();
         }
 
         /// <summary>
@@ -55,7 +55,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns></returns>
         public Task<List<T>> GetAllFromCacheAsync()
         {
-            return DataContext.Set<T>().Cacheable().ToListAsync();
+            return DataContext.Set<T>().AsNoTracking().Cacheable().ToListAsync();
         }
 
         /// <summary>
@@ -75,7 +75,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns></returns>
         public virtual List<TDto> GetAllFromCache<TDto>() where TDto : class
         {
-            return DataContext.Set<T>().AsNoTracking().ProjectTo<TDto>(MapperConfig).Cacheable().ToList();
+            return DataContext.Set<T>().ProjectTo<TDto>(MapperConfig).Cacheable().ToList();
         }
 
         /// <summary>
@@ -85,7 +85,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns></returns>
         public Task<List<TDto>> GetAllFromCacheAsync<TDto>() where TDto : class
         {
-            return DataContext.Set<T>().AsNoTracking().ProjectTo<TDto>(MapperConfig).Cacheable().ToListAsync();
+            return DataContext.Set<T>().ProjectTo<TDto>(MapperConfig).Cacheable().ToListAsync();
         }
 
         /// <summary>
@@ -121,7 +121,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns></returns>
         public virtual List<T> GetAllFromCache<TS>(Expression<Func<T, TS>> orderby, bool isAsc = true)
         {
-            return GetAll(orderby, isAsc).Cacheable().ToList();
+            return GetAllNoTracking(orderby, isAsc).Cacheable().ToList();
         }
 
         /// <summary>
@@ -133,7 +133,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns></returns>
         public Task<List<T>> GetAllFromCacheAsync<TS>(Expression<Func<T, TS>> @orderby, bool isAsc = true)
         {
-            return GetAll(orderby, isAsc).Cacheable().ToListAsync();
+            return GetAllNoTracking(orderby, isAsc).Cacheable().ToListAsync();
         }
 
         /// <summary>
@@ -159,7 +159,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns>还未执行的SQL语句</returns>
         public virtual List<TDto> GetAllFromCache<TS, TDto>(Expression<Func<T, TS>> orderby, bool isAsc = true) where TDto : class
         {
-            return GetAllNoTracking(orderby, isAsc).ProjectTo<TDto>(MapperConfig).Cacheable().ToList();
+            return GetAll(orderby, isAsc).ProjectTo<TDto>(MapperConfig).Cacheable().ToList();
         }
 
         /// <summary>
@@ -172,7 +172,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns></returns>
         public Task<List<TDto>> GetAllFromCacheAsync<TS, TDto>(Expression<Func<T, TS>> @orderby, bool isAsc = true) where TDto : class
         {
-            return GetAllNoTracking(orderby, isAsc).ProjectTo<TDto>(MapperConfig).Cacheable().ToListAsync();
+            return GetAll(orderby, isAsc).ProjectTo<TDto>(MapperConfig).Cacheable().ToListAsync();
         }
 
         /// <summary>
@@ -205,7 +205,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns></returns>
         public virtual List<T> GetQueryFromCache(Expression<Func<T, bool>> @where)
         {
-            return DataContext.Set<T>().Where(where).Cacheable().ToList();
+            return DataContext.Set<T>().Where(where).AsNoTracking().Cacheable().ToList();
         }
 
         /// <summary>
@@ -215,7 +215,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns></returns>
         public Task<List<T>> GetQueryFromCacheAsync(Expression<Func<T, bool>> @where)
         {
-            return DataContext.Set<T>().Where(where).Cacheable().ToListAsync();
+            return DataContext.Set<T>().Where(where).AsNoTracking().Cacheable().ToListAsync();
         }
 
         /// <summary>
@@ -228,7 +228,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns></returns>
         public virtual List<T> GetQueryFromCache<TS>(Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc = true)
         {
-            return GetQuery(where, orderby, isAsc).Cacheable().ToList();
+            return GetQueryNoTracking(where, orderby, isAsc).Cacheable().ToList();
         }
 
         /// <summary>
@@ -241,7 +241,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns></returns>
         public Task<List<T>> GetQueryFromCacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
         {
-            return GetQuery(where, orderby, isAsc).Cacheable().ToListAsync();
+            return GetQueryNoTracking(where, orderby, isAsc).Cacheable().ToListAsync();
         }
 
         /// <summary>
@@ -312,7 +312,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns>实体集合</returns>
         public virtual List<TDto> GetQueryFromCache<TDto>(Expression<Func<T, bool>> where) where TDto : class
         {
-            return DataContext.Set<T>().Where(where).AsNoTracking().ProjectTo<TDto>(MapperConfig).Cacheable().ToList();
+            return DataContext.Set<T>().Where(where).ProjectTo<TDto>(MapperConfig).Cacheable().ToList();
         }
 
         /// <summary>
@@ -322,7 +322,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns></returns>
         public Task<List<TDto>> GetQueryFromCacheAsync<TDto>(Expression<Func<T, bool>> @where) where TDto : class
         {
-            return DataContext.Set<T>().Where(where).AsNoTracking().ProjectTo<TDto>(MapperConfig).Cacheable().ToListAsync();
+            return DataContext.Set<T>().Where(where).ProjectTo<TDto>(MapperConfig).Cacheable().ToListAsync();
         }
 
         /// <summary>
@@ -336,7 +336,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns></returns>
         public virtual List<TDto> GetQueryFromCache<TS, TDto>(Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc = true) where TDto : class
         {
-            return GetQueryNoTracking(where, orderby, isAsc).ProjectTo<TDto>(MapperConfig).Cacheable().ToList();
+            return GetQuery(where, orderby, isAsc).ProjectTo<TDto>(MapperConfig).Cacheable().ToList();
         }
 
         /// <summary>
@@ -356,7 +356,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns>实体</returns>
         public virtual T GetFromCache(Expression<Func<T, bool>> where)
         {
-            return DataContext.Set<T>().Where(where).DeferredFirstOrDefault().Execute();
+            return DataContext.Set<T>().Where(where).AsNoTracking().DeferredFirstOrDefault().Execute();
         }
 
         /// <summary>
@@ -366,7 +366,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns>实体</returns>
         public Task<T> GetFromCacheAsync(Expression<Func<T, bool>> @where)
         {
-            return DataContext.Set<T>().Where(where).DeferredFirstOrDefault().ExecuteAsync();
+            return DataContext.Set<T>().Where(where).AsNoTracking().DeferredFirstOrDefault().ExecuteAsync();
         }
 
         /// <summary>
@@ -392,7 +392,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns>实体</returns>
         public virtual T GetFromCache<TS>(Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc = true)
         {
-            return isAsc ? DataContext.Set<T>().OrderBy(orderby).Where(where).DeferredFirstOrDefault().Execute() : DataContext.Set<T>().OrderByDescending(orderby).Where(where).DeferredFirstOrDefault().Execute();
+            return isAsc ? DataContext.Set<T>().OrderBy(orderby).Where(where).AsNoTracking().DeferredFirstOrDefault().Execute() : DataContext.Set<T>().OrderByDescending(orderby).Where(where).AsNoTracking().DeferredFirstOrDefault().Execute();
         }
 
         /// <summary>
@@ -405,7 +405,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns>实体</returns>
         public Task<T> GetFromCacheAsync<TS>(Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
         {
-            return isAsc ? DataContext.Set<T>().OrderBy(orderby).Where(where).DeferredFirstOrDefault().ExecuteAsync() : DataContext.Set<T>().OrderByDescending(orderby).Where(where).DeferredFirstOrDefault().ExecuteAsync();
+            return isAsc ? DataContext.Set<T>().OrderBy(orderby).Where(where).AsNoTracking().DeferredFirstOrDefault().ExecuteAsync() : DataContext.Set<T>().OrderByDescending(orderby).Where(where).AsNoTracking().DeferredFirstOrDefault().ExecuteAsync();
         }
 
         /// <summary>
@@ -625,7 +625,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns></returns>
         public virtual PagedList<T> GetPagesFromCache<TS>(int pageIndex, int pageSize, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc)
         {
-            var temp = DataContext.Set<T>().Where(where);
+            var temp = DataContext.Set<T>().Where(where).AsNoTracking();
             return isAsc ? temp.OrderBy(orderby).ToCachedPagedList(pageIndex, pageSize) : temp.OrderByDescending(orderby).ToCachedPagedList(pageIndex, pageSize);
         }
 
@@ -641,7 +641,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns></returns>
         public virtual Task<PagedList<T>> GetPagesFromCacheAsync<TS>(int pageIndex, int pageSize, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc)
         {
-            var temp = DataContext.Set<T>().Where(where);
+            var temp = DataContext.Set<T>().Where(where).AsNoTracking();
             return isAsc ? temp.OrderBy(orderby).ToCachedPagedListAsync(pageIndex, pageSize) : temp.OrderByDescending(orderby).ToCachedPagedListAsync(pageIndex, pageSize);
         }
 

+ 1 - 40
src/Masuit.MyBlogs.Core/Infrastructure/Repository/CommentRepository.cs

@@ -1,8 +1,5 @@
 using Masuit.MyBlogs.Core.Infrastructure.Repository.Interface;
 using Masuit.MyBlogs.Core.Models.Entity;
-using Masuit.Tools.Models;
-using Microsoft.EntityFrameworkCore;
-using System.Linq.Expressions;
 
 namespace Masuit.MyBlogs.Core.Infrastructure.Repository
 {
@@ -18,41 +15,5 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
             DataContext.Add(t);
             return t;
         }
-
-        /// <summary>
-        /// 根据ID找实体(异步)
-        /// </summary>
-        /// <param name="id">实体id</param>
-        /// <returns>实体</returns>
-        public override Task<Comment> GetByIdAsync(int id)
-        {
-            return EF.CompileAsyncQuery((DataContext ctx, int cid) => ctx.Comment.Include(c => c.Children).ThenInclude(c => c.Children).ThenInclude(c => c.Children).FirstOrDefault(c => c.Id == cid))(DataContext, id);
-        }
-
-        /// <summary>
-        /// 根据ID找实体
-        /// </summary>
-        /// <param name="id">实体id</param>
-        /// <returns>实体</returns>
-        public override Comment GetById(int id)
-        {
-            return EF.CompileQuery((DataContext ctx, int cid) => ctx.Comment.Include(c => c.Children).ThenInclude(c => c.Children).ThenInclude(c => c.Children).FirstOrDefault(c => c.Id == cid))(DataContext, id);
-        }
-
-        /// <summary>
-        /// 高效分页查询方法
-        /// </summary>
-        /// <typeparam name="TS"></typeparam>
-        /// <param name="pageIndex">第几页</param>
-        /// <param name="pageSize">每页大小</param>
-        /// <param name="where">where Lambda条件表达式</param>
-        /// <param name="orderby">orderby Lambda条件表达式</param>
-        /// <param name="isAsc">升序降序</param>
-        /// <returns>还未执行的SQL语句</returns>
-        public override Task<PagedList<Comment>> GetPagesAsync<TS>(int pageIndex, int pageSize, Expression<Func<Comment, bool>> @where, Expression<Func<Comment, TS>> @orderby, bool isAsc)
-        {
-            var temp = DataContext.Comment.Include(c => c.Children).ThenInclude(c => c.Children).ThenInclude(c => c.Children).Where(where);
-            return isAsc ? temp.OrderBy(orderby).ToPagedListAsync(pageIndex, pageSize) : temp.OrderByDescending(orderby).ToPagedListAsync(pageIndex, pageSize);
-        }
     }
-}
+}

+ 1 - 40
src/Masuit.MyBlogs.Core/Infrastructure/Repository/LeaveMessageRepository.cs

@@ -1,8 +1,5 @@
 using Masuit.MyBlogs.Core.Infrastructure.Repository.Interface;
 using Masuit.MyBlogs.Core.Models.Entity;
-using Masuit.Tools.Models;
-using Microsoft.EntityFrameworkCore;
-using System.Linq.Expressions;
 
 namespace Masuit.MyBlogs.Core.Infrastructure.Repository
 {
@@ -18,41 +15,5 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
             DataContext.Add(t);
             return t;
         }
-
-        /// <summary>
-        /// 根据ID找实体(异步)
-        /// </summary>
-        /// <param name="id">实体id</param>
-        /// <returns>实体</returns>
-        public override Task<LeaveMessage> GetByIdAsync(int id)
-        {
-            return EF.CompileAsyncQuery((DataContext ctx, int cid) => ctx.LeaveMessage.Include(c => c.Children).ThenInclude(c => c.Children).ThenInclude(c => c.Children).FirstOrDefault(c => c.Id == cid))(DataContext, id);
-        }
-
-        /// <summary>
-        /// 根据ID找实体
-        /// </summary>
-        /// <param name="id">实体id</param>
-        /// <returns>实体</returns>
-        public override LeaveMessage GetById(int id)
-        {
-            return EF.CompileQuery((DataContext ctx, int cid) => ctx.LeaveMessage.Include(c => c.Children).ThenInclude(c => c.Children).ThenInclude(c => c.Children).FirstOrDefault(c => c.Id == cid))(DataContext, id);
-        }
-
-        /// <summary>
-        /// 高效分页查询方法
-        /// </summary>
-        /// <typeparam name="TS"></typeparam>
-        /// <param name="pageIndex">第几页</param>
-        /// <param name="pageSize">每页大小</param>
-        /// <param name="where">where Lambda条件表达式</param>
-        /// <param name="orderby">orderby Lambda条件表达式</param>
-        /// <param name="isAsc">升序降序</param>
-        /// <returns>还未执行的SQL语句</returns>
-        public override Task<PagedList<LeaveMessage>> GetPagesAsync<TS>(int pageIndex, int pageSize, Expression<Func<LeaveMessage, bool>> @where, Expression<Func<LeaveMessage, TS>> @orderby, bool isAsc)
-        {
-            var temp = DataContext.LeaveMessage.Include(c => c.Children).ThenInclude(c => c.Children).ThenInclude(c => c.Children).Where(where);
-            return isAsc ? temp.OrderBy(orderby).ToPagedListAsync(pageIndex, pageSize) : temp.OrderByDescending(orderby).ToPagedListAsync(pageIndex, pageSize);
-        }
     }
-}
+}

+ 1 - 24
src/Masuit.MyBlogs.Core/Infrastructure/Repository/MenuRepository.cs

@@ -19,28 +19,5 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
             DataContext.Add(t);
             return t;
         }
-
-        /// <summary>
-        /// 基本查询方法,获取一个集合
-        /// </summary>
-        /// <typeparam name="TS">排序</typeparam>
-        /// <param name="where">查询条件</param>
-        /// <param name="orderby">排序字段</param>
-        /// <param name="isAsc">是否升序</param>
-        /// <returns>还未执行的SQL语句</returns>
-        public override IOrderedQueryable<Menu> GetQuery<TS>(Expression<Func<Menu, bool>> @where, Expression<Func<Menu, TS>> @orderby, bool isAsc = true)
-        {
-            return isAsc ? DataContext.Menu.Include(m => m.Children).ThenInclude(m => m.Children).ThenInclude(m => m.Children).Where(where).OrderBy(orderby) : DataContext.Menu.Include(m => m.Children).ThenInclude(m => m.Children).ThenInclude(m => m.Children).Where(where).OrderByDescending(orderby);
-        }
-
-        /// <summary>
-        /// 基本查询方法,获取一个集合,优先从二级缓存读取
-        /// </summary>
-        /// <param name="where">查询条件</param>
-        /// <returns>还未执行的SQL语句</returns>
-        public override List<Menu> GetQueryFromCache(Expression<Func<Menu, bool>> @where)
-        {
-            return DataContext.Menu.Include(m => m.Children).ThenInclude(m => m.Children).ThenInclude(m => m.Children).Where(where).Cacheable().ToList();
-        }
     }
-}
+}

+ 16 - 12
src/Masuit.MyBlogs.Core/Infrastructure/Services/CategoryService.cs

@@ -2,6 +2,7 @@
 using Masuit.MyBlogs.Core.Infrastructure.Repository.Interface;
 using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
 using Masuit.MyBlogs.Core.Models.Entity;
+using Masuit.Tools.Models;
 
 namespace Masuit.MyBlogs.Core.Infrastructure.Services
 {
@@ -21,25 +22,28 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
         {
             var category = await GetByIdAsync(id);
             var moveCat = await GetByIdAsync(mid);
-            for (var j = 0; j < category.Post.Count; j++)
+            foreach (var c in category.Flatten())
             {
-                var p = category.Post.ElementAt(j);
-                moveCat.Post.Add(p);
-                for (var i = 0; i < p.PostHistoryVersion.Count; i++)
+                for (var j = 0; j < c.Post.Count; j++)
                 {
-                    moveCat.PostHistoryVersion.Add(p.PostHistoryVersion.ElementAt(i));
+                    var p = c.Post.ElementAt(j);
+                    moveCat.Post.Add(p);
+                    for (var i = 0; i < p.PostHistoryVersion.Count; i++)
+                    {
+                        moveCat.PostHistoryVersion.Add(p.PostHistoryVersion.ElementAt(i));
+                    }
                 }
-            }
 
-            for (var i = 0; i < category.PostHistoryVersion.Count; i++)
-            {
-                var p = category.PostHistoryVersion.ElementAt(i);
-                p.CategoryId = moveCat.Id;
-                moveCat.PostHistoryVersion.Add(p);
+                for (var i = 0; i < c.PostHistoryVersion.Count; i++)
+                {
+                    var p = c.PostHistoryVersion.ElementAt(i);
+                    p.CategoryId = moveCat.Id;
+                    moveCat.PostHistoryVersion.Add(p);
+                }
             }
 
             bool b = await DeleteByIdAsync(id) > 0;
             return b;
         }
     }
-}
+}

+ 1 - 1
src/Masuit.MyBlogs.Core/Infrastructure/Services/CommentService.cs

@@ -11,4 +11,4 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
         {
         }
     }
-}
+}

+ 1 - 8
src/Masuit.MyBlogs.Core/Infrastructure/Services/Interface/IMenuService.cs

@@ -4,12 +4,5 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services.Interface
 {
     public partial interface IMenuService : IBaseService<Menu>
     {
-        /// <summary>
-        /// 通过存储过程获得自己以及自己所有的子元素集合
-        /// </summary>
-        /// <param name="id"></param>
-        /// <returns></returns>
-        IEnumerable<Menu> GetChildrenMenusByParentId(int id);
-
     }
-}
+}

+ 1 - 33
src/Masuit.MyBlogs.Core/Infrastructure/Services/MenuService.cs

@@ -10,37 +10,5 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
         public MenuService(IBaseRepository<Menu> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
-
-        /// <summary>
-        /// 通过存储过程获得自己以及自己所有的子元素集合
-        /// </summary>
-        /// <param name="id"></param>
-        /// <returns></returns>
-        public IEnumerable<Menu> GetChildrenMenusByParentId(int id)
-        {
-            Menu c = GetFromCache(m => m.Id == id);
-            var menus = new List<Menu>() { c };
-            GetChildrenMenusByParentId(c, menus);
-            return menus;
-        }
-
-        /// <summary>
-        /// 通过存储过程获得自己以及自己所有的子元素集合
-        /// </summary>
-        /// <param name="id"></param>
-        /// <returns></returns>
-        private void GetChildrenMenusByParentId(Menu menu, List<Menu> list)
-        {
-            var menus = GetQueryFromCache(x => x.ParentId == menu.Id).ToList();
-            if (menus.Any())
-            {
-                list.AddRange(menus);
-                foreach (var c in menus)
-                {
-                    GetChildrenMenusByParentId(c, list);
-                }
-            }
-        }
-
     }
-}
+}

+ 3 - 1
src/Masuit.MyBlogs.Core/Models/Entity/Comment.cs

@@ -94,6 +94,8 @@ namespace Masuit.MyBlogs.Core.Models.Entity
         /// </summary>
         public string Location { get; set; }
 
+        public string GroupTag { get; set; }
+
         [ForeignKey("PostId")]
         public virtual Post Post { get; set; }
 
@@ -107,4 +109,4 @@ namespace Masuit.MyBlogs.Core.Models.Entity
         /// </summary>
         public virtual Comment Parent { get; set; }
     }
-}
+}

+ 3 - 1
src/Masuit.MyBlogs.Core/Models/Entity/LeaveMessage.cs

@@ -78,6 +78,8 @@ namespace Masuit.MyBlogs.Core.Models.Entity
         /// </summary>
         public string Location { get; set; }
 
+        public string GroupTag { get; set; }
+
         /// <summary>
         /// ¸¸½Úµã
         /// </summary>
@@ -88,4 +90,4 @@ namespace Masuit.MyBlogs.Core.Models.Entity
         /// </summary>
         public virtual ICollection<LeaveMessage> Children { get; set; }
     }
-}
+}

+ 2 - 1
src/Masuit.MyBlogs.Core/Views/Shared/_Layout.cshtml

@@ -10,10 +10,11 @@
 @using Masuit.Tools
 @using Masuit.Tools.Core.Net
 @using EFCoreSecondLevelCacheInterceptor
+@using Masuit.Tools.Models
 @using Microsoft.AspNetCore.Http.Extensions
 @{
     string[] colors = { "success", "info", "warning", "danger", "default" };
-    List<Menu> menus = _menuService.GetQueryFromCache(m => m.ParentId == null && m.Status == Status.Available).OrderBy(m => m.Sort).ToList();
+    List<Menu> menus = _menuService.GetQueryFromCache(m => m.Status == Status.Available,m => m.Sort).ToList().ToTree(m => m.Id,m => m.ParentId);
     var user = Context.Session.Get<UserInfoDto>(SessionKey.UserInfo) ?? new UserInfoDto();
     var links = _linksService.GetQuery(l => l.Status == Status.Available).OrderByDescending(l => l.Recommend).ThenByDescending(l => l.Loopbacks.GroupBy(x => x.IP).Count()).Take(30).Select(e => new{e.Url,e.Name}).Cacheable().ToList();
 }