[英]Recursive query takes too much time to load data in C#
*我寫了一個遞歸查詢來獲得無限的菜單層。 查詢可以很好地提供准確的結果,但加載時間太長。 大概需要 10 到 15 秒。 如果我需要做任何事情來提高性能,請幫助我。 我已經提供了所有代碼來找出問題所在。 為了從實體映射到視圖 model 我使用了自動映射器。 *
實體:
public class Menus
{
public int Id { get; set; }
public string Icon { get; set; }
public string Label { get; set; }
public string To { get; set; }
[ForeignKey("Parents")]
public int? ParentsId { get; set; }
public string Key { get; set; }
public bool? Permitted { get; set; }
public Menus Parents { get; set; }
public ICollection<Menus> Subs { get; set; }
public ICollection<MenusRole> MenusRoles { get; set; }
}
詢問:
public async Task<IEnumerable<Menus>> GetAllMenusAsync()
{
List<Menus> temp = await ApplicationDbContext
.Menus
.Include(x => x.Subs)
.Where(x => x.Parents == null)
.Select(f => new Menus
{
Id = f.Id,
Key = f.Key,
Label = f.Label,
To = f.To,
Icon = f.Icon,
ParentsId = f.ParentsId,
Subs = f.Subs
}).ToListAsync();
return Get_all_menus(temp);
}
public List<Menus> Get_all_menus(List<Menus> menus)
{
int z = 0;
List<Menus> menuList = new List<Menus>();
if (menus.Count > 0)
{
menuList.AddRange(menus);
}
foreach (Menus item in menus)
{
Menus menu = ApplicationDbContext
.Menus
.Include(y => y.Subs)
.Where(y => y.Id == item.Id)
.Select(y => new Menus
{
Id = y.Id,
Key = y.Key,
Label = y.Label,
To = y.To,
Icon = y.Icon,
ParentsId = y.ParentsId,
Subs = y.Subs,
Permitted = true
}).First();
if (menu.Subs == null)
{
z++;
continue;
}
List<Menus> subMenu = menu.Subs.ToList();
menu.Subs = Get_all_menus(subMenu);
menuList[z] = menu;
z++;
}
return menuList;
}
在 Controller
[HttpGet("get-all-menus")]
public async Task<ActionResult> GetAllMenus()
{
var menus = await _menusService.GetAllMenus();
var menusResources = _mapper.Map<IEnumerable<Menus>, IEnumerable<MenusResourceForSidebar>>(menus);
return Ok(menusResources);
}
查看Model
public string Id { get; set; }
public string Icon { get; set; }
public string Label { get; set; }
public string To { get; set; }
public bool? Permitted { get; set; }
public ICollection<MenusResourceForSidebar> Subs { get; set; }
與其加載根菜單,然后在單獨的查詢中加載子項,不如在一個查詢中加載整個集合,然后填充導航鏈接。
public async Task<IEnumerable<Menus>> GetAllMenusAsync()
{
List<Menus> temp = await ApplicationDbContext.Menus.ToList();
List<Menus> topLevel = new List<Menu>();
foreach (var menu in temp)
{
if (menu.ParentsId == null)
{
topLevel.Add(menu);
continue;
}
var parent = temp.Find(x => x.Id == temp.ParentsId.Value);
if (parent.Subs == null)
parent.Subs = new List<Menus>();
parent.Subs.Add(menu);
}
return topLevel;
}
你應該能夠做到:
context.Menus.Include(m => m.Subs).ToList();
EFCore 中的關系修復將為您將所有菜單鏈接在一起。 在以后的 EF 中,您甚至不需要 Include..
context.Menus.ToList();
這是 SSMS 中的一個表:
這是數據:
在這里,它在繪圖程序中被切碎並重新排列成一棵樹:
這是腳手架實體:
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
#nullable disable
using System.Collections.Generic;
namespace ConsoleApp7net5.Models
{
public partial class Menu
{
public Menu()
{
InverseParent = new HashSet<Menu>();
}
public int Id { get; set; }
public int? ParentId { get; set; }
public string Label { get; set; }
public virtual Menu Parent { get; set; }
public virtual ICollection<Menu> InverseParent { get; set; }
}
}
這是我們在要求 EFC(在我的例子中是 5)僅使用 ToList 下載所有內容后看到的內容:
當然,從根開始可能是有意義的(或多個根,但我的數據只有一個)
不要給類復數名稱(菜單),順便說一句,如果它們不是集合/可枚舉(父母),也不要給屬性復數名稱 - 這會導致代碼非常混亂
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.