我目前正在使用ASP.NET MVC和Angular開發一個Web應用程序。我希望能夠做的是根據每個用戶的角色獲取導航項目列表,將它們全部存儲在對象列表中,並將其序列化爲JSON以返回角度。ASP .NET獲取數據太慢
我的方法目前工作得很好,但數據至少需要5秒才能打開頁面,而我的頁面在不到一秒鐘內加載。因此,我的用戶只是坐在那裏等待導航菜單彈出,這是不好的。
這裏是我使用這兩種方法:
public NavDirectoryViewModel GetAllUserNavItems(string UserId)
{
NavDirectoryViewModel model = new NavDirectoryViewModel();
model.NavItems = new List<NavViewModel>();
foreach (var nav in GetAllNavItems())
{
if (GetUserNavItem(UserId, nav) != null)
{
if (nav.ParentId == 0)
model.NavItems.Add(GetUserNavItem(UserId, nav));
}
}
model.NavItems = model.NavItems.OrderBy(x => x.SortOrder).ToList();
return model;
}
public NavViewModel GetUserNavItem(string UserId, NavModel model)
{
try
{
if(model.AllowedUsers.FirstOrDefault(x => x.UserId.Equals(UserId)) != null || model.AllowedRoles.FirstOrDefault(x => x.Role.Users.FirstOrDefault(y => y.UserId.Equals(UserId)) != null) != null)
{
return new NavViewModel { Name = model.Name, Href = model.Href, Image = model.Image, SortOrder = model.SortOrder, SubItems = GetNavItems(model.Id).Where(x => x.ParentId == model.Id).Select(x => GetUserNavItem(UserId, x)).ToList() };
}
else
{
return null;
}
}
catch(Exception e1) { return null; }
}
這裏有兩種型號:
public class NavViewModel
{
public string Name { get; set; }
public string Href { get; set; }
public string Image { get; set; }
public int? SortOrder { get; set; }
public List<NavViewModel> SubItems { get; set; }
}
public class NavModel
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Href { get; set; }
public string Image { get; set; }//string of server image path or fa class
public int ParentId { get; set; }//Will be 0 if it has no parent
public int? SortOrder { get; set; }
public virtual List<NavModel> SubItems { get; set; }
public virtual List<RoleNavAuthorizationModel> AllowedRoles { get; set; }
public virtual List<UserNavAuthorizationModel> AllowedUsers { get; set; }
}
中的作用和UserNavAuthorizationModels只存儲NavItem Id和角色/用戶ID是允許查看導航項目。
最初我正在序列化需要10-15秒的NavModel,所以我製作了一個視圖模型,它沒有存儲儘可能多的數據,並且稍微加快了速度。但是,我無法讓我的用戶在加載其他所有內容時等待導航欄加載。
調試時,我發現它是GetUserNavItem
方法,這是需要一段時間。其他一切都運行得非常快。
有沒有人對如何加快東西有什麼建議?
更新
這裏是GetAllNavItems()
代碼:
public List<NavModel> GetAllNavItems() { return db.NavItems.ToList(); }
更新
我上緩存了的Ondrej Svejdar的建議,現在存儲JSON在用戶的會話所以如果頁面在其會話處於活動狀態時重新加載,則根本不需要任何時間重裝。我把它放在我的控制器中:
if (HttpContext.Cache[User.Identity.GetUserId() + "NAV"] == null)
{
string NavJSON = JsonConvert.SerializeObject(nrepo.GetAllUserNavItems(User.Identity.GetUserId()), Formatting.Indented, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
HttpContext.Cache[User.Identity.GetUserId() + "NAV"] = NavJSON;
return Json(NavJSON, JsonRequestBehavior.AllowGet);
}
else
{
string NavJSON = HttpContext.Cache[User.Identity.GetUserId() + "NAV"].ToString();
return Json(NavJSON, JsonRequestBehavior.AllowGet);
}
第一個問題是,你調用'GetUserNavItem'兩次,一次是在'如果(GetUserNavItem(用戶ID,NAV)!= NULL)'然後再'如果(nav.ParentId == 0)',你可以做該調用一旦將其分配給一個變量,然後使用變量值而不是再次調用該方法。 – Corporalis
如果您分享更多的代碼,這將有所幫助。一般來說,最好的做法是a)從數據庫加載所有可能的導航節點並緩存它 - 在我看來,您正在逐節點加載它b)按用戶請求從緩存的節點列表中選擇合適的節點(在a)中檢索以構建導航樹 –
其他問題是在此處調用GetUserNavItem和GetNavItems的遞歸,這將運行這些昂貴的查詢......它需要進行重大的重構。還有其他更有效的方法來存儲/構建導航樹。然而,在這種情況下緩存應該至少可以幫助你如何做到這一點。 –