【问题标题】:Lazy loading on DynamicSitemapNodeProviderDynamicSitemapNodeProvider 上的延迟加载
【发布时间】:2013-11-18 10:19:14
【问题描述】:

我已经使用 MvcSiteMapProvider 设置了一个面包屑。 我有一个结构,它有一些静态节点,然后在一些叶子上有使用 asp.net-attribute 添加的动态节点。

[MvcSiteMapNode(DynamicNodeProvider = "Web.DealerNet.CommonFramework.UserDynamicNodeProvider)]

“工作”很好,但是当您深入了解时,性能真的很差,因为在启动时所有用户都被加载到内存中,并且为每个用户创建了一个节点。 这是official docu 中建议的方法。有没有办法在这里使用延迟加载? (当它真正被调用时加载用户对象的属性,而不是为每个用户创建一个节点......我在那里有大约 20k 个用户......)

public class UserDynamicNodeProvider : DynamicNodeProviderBase
    {
        public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node)
        {

            UserDao dao = DependencyResolver.Current.GetService<UserDao>();

            // Create a node for each element 
            foreach (User user in dao.GetAll())
            {   
                DynamicNode dynamicNode = new DynamicNode();
                dynamicNode.Title = user.UserName;
                dynamicNode.Description = user.UserName;
                dynamicNode.RouteValues.Add("id", user.IdUser);
                dynamicNode.ParentKey = "TheParentKey";
                dynamicNode.Clickable = false;
                dynamicNode.Area = "MyArea";

                yield return dynamicNode;
            }

        }

    }

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-4 mvcsitemapprovider asp.net-mvc-sitemap


    【解决方案1】:

    目前不支持延迟加载(尽管计划在 v5 中添加请求级节点)。

    目前,用户列表听起来并不像是您需要在搜索引擎中编制索引的内容(除非您碰巧正在构建一个社交网站)。每个用户都不需要 /sitemap.xml 端点中的单独条目。因此,为每个用户添加一个节点几乎没有什么价值。

    如果是这种情况,更好的方法是使用preservedRouteParameters 强制所有请求匹配单个节点,然后使用visibility providersSiteMapTitleAttribute 调整Menu 和SiteMapPath HTML 帮助器的显示方式。

    [MvcSiteMapNode(Area="MyArea", PreservedRouteParameters="id", Clickable="False")]
    

    并且在您的控制器操作中,将节点(或其父节点)的标题设置为正确的用户。

    [SiteMapTitle("UserName")] 
    public ViewResult Details(int id) { 
       UserDao dao = DependencyResolver.Current.GetService<UserDao>();
    
       // This example assumes your user model object has a public property "UserName"
       var user = dao.Find(id); 
       return View(user); 
    }
    

    这将复制每个请求的 id 以使其匹配每个请求,从而为面包屑路径中的每个用户提供一个节点的外观。通常,您需要使用 FilteredSiteMapNodeVisibilityProvider 从菜单中隐藏这个“幽灵”节点——使用这种方法时,无法列出菜单中的所有用户。如果您需要所有用户的列表,我建议您创建一个直接从数据库加载的列表。

    在帖子How to Make MvcSiteMapProvider Remember a User's Position 上查看一些可下载的演示。

    另一方面,如果您正在构建一个社交网站,我建议extending the cache 将其缓存到磁盘而不是全部保存在内存中。这不会缩短初始启动时间,但可以防止您用尽服务器的所有内存。网上有一个open source file cache 和一些instructions on how you could build your implmentation。如果您注意重新加载缓存的频率,这种方法可能适合您。

    另一个可能导致性能问题的问题是您使用 DependencyResolver 作为服务定位器(即anti-pattern)。假设您使用外部 DI,通过构造函数注入依赖项可确保您的 DI 容器(而不是应用程序)控制对象的生命周期。

    public class UserDynamicNodeProvider : DynamicNodeProviderBase
    {
        private readonly UserDao userDao;
    
        public UserDynamicNodeProvider(UserDao userDao)
        {
            if (userDao == null)
                throw new ArgumentNullException("userDao");
    
            this.userDao = userDao;
        }
    
        public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node)
        {
            // Create a node for each element 
            foreach (User user in this.userDao.GetAll())
            {   
                DynamicNode dynamicNode = new DynamicNode();
                dynamicNode.Title = user.UserName;
                dynamicNode.Description = user.UserName;
                dynamicNode.RouteValues.Add("id", user.IdUser);
                dynamicNode.ParentKey = "TheParentKey";
                dynamicNode.Clickable = false;
                dynamicNode.Area = "MyArea";
    
                yield return dynamicNode;
            }
        }
    }
    

    Microsoft 不鼓励在您自己的应用程序代码中使用 DependencyResolver.Current(请参阅 Professional ASP.NET MVC 4,Wrox Press,第 308 页 - 由 Jon Galloway、Phil Haack、Brad Wilson 和 K. Scott Allen 撰写),并且严格执行将您的类绑定到 MVC 框架。

    【讨论】:

    • 我没有意识到我只需要用于爬虫的 dynamicNodeProvider ......正如你所说,我完全可以只使用这两个属性。 tyvm!
    猜你喜欢
    • 1970-01-01
    • 2012-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-22
    • 1970-01-01
    • 2011-03-14
    相关资源
    最近更新 更多