Umbraco发布了活动表演

时间:2015-10-29 10:29:22

标签: umbraco

我有一个评论类型结构,用户可以在其中发布对文章的回复。 (一篇文章可以有很多讨论回复)。当用户添加回复时,我希望父文章的上次更新日期也发生变化,以便在从前端查看时,文章被放置在列表的顶部,表明它已有最近的活动。为了实现这一点,评论是通过自定义控制器添加的,然后我使用ContentService Published事件来更新父级,但我发现我的事件有点瓶颈并且需要花费6秒才能运行

public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
    ContentService.Published += ContentServicePublished;
}

private void ContentServicePublished(IPublishingStrategy sender, PublishEventArgs<IContent> e)
{
    foreach (var node in e.PublishedEntities)
    {
        //Handle updating the parent nodes last edited date to address ordering
        if (node.ContentType.Alias == "DiscussionReply")
        {
            var contentService = new Umbraco.Core.Services.ContentService();
            var parentNode = contentService.GetById(node.ParentId);
            int intSiblings = parentNode.Children().Count() + 1;

            if(parentNode.HasProperty("siblings"))
            {
                parentNode.SetValue("siblings", intSiblings);
                contentService.SaveAndPublishWithStatus(parentNode, 0, false);
            }
        }
    }
}

此代码是否有明显的问题导致性能问题?

非常感谢,

2 个答案:

答案 0 :(得分:1)

您应该使用服务单身人士来访问各种服务,包括ContentService

这样做的一种方法是访问ApplicationContext.Current上的服务,如下所示:

var contentService = ApplicationContext.Current.Services.ContentService;

但是,您的瓶颈将是检索父节点及其属性,这需要多次调用数据库。最重要的是,您可以在此处检索父母的孩子:

int intSiblings = parentNode.Children().Count() + 1;

更好的解决方案是使用PublishedContent缓存,它根本不会访问数据库并提供显着优越的性能。

如果您正在使用SurfaceController使用它的Umbraco媒体资源(并且您也可以访问Services):

// After you've published the comment node:
var commentNode = Umbraco.TypedContent(commentNodeId);

// We already know this is a DiscussionReply node, no need to check.

int intSiblings = commentNode.Parent.Children.Count() + 1;

if (commentNode.Parent.HasProperty("siblings")) 
{
    // It's only now that we really need to grab the parent node from the ContentService so we can update it.
    var parentNode = Services.ContentService.GetById(commentNode.ParentId);
    parentNode.SetValue("siblings", intSiblings);
    contentService.SaveAndPublishWithStatus(parentNode, 0, false);
}

如果您正在基于UmbracoApiController实施WebApi,那么您也可以使用相同的UmbracoServices属性。

答案 1 :(得分:0)

我正在使用Umbraco 7.3.4,这是我的解决方案:

// Create a list of objects to be created or updated.
var newContentList = new List<MyCustomModel>() {
 new MyCustomModel {Id: 1, Name: "Document 1", Attribute1: ...},
 new MyCustomModel {Id: 2, Name: "Document 2", Attribute1: ...},
 new MyCustomModel {Id: 3, Name: "Document 3", Attribute1: ...}
};

// Get old content from cache
var oldContentAsIPublishedContentList = (new UmbracoHelper(UmbracoContext.Current)).TypedContent(ParentId).Descendants("YourContentType").ToList();

// Get only modified content items
var modifiedItemIds = from x in oldContentAsIPublishedContentList
                           from y in newContentList 
                           where x.Id == y.Id
                           && (x.Name != y.Name || x.Attribute1 != y.Attribute1)
                           select x.Id;

// Get modified items as an IContent list.
var oldContentAsIContentList = ApplicationContext.Services.ContentService.GetByIds(modifiedItemIds).ToList();

// Create final content list.
var finalContentList= new List<IContent>();

// Update or insert items
foreach(var item in newContentList) {
    // For each new content item, find an old IContent by the ID
    // If the old IContent is found and the values are modified, add it to the finalContentList
    // Otherwise, create a new instance using the API.
    IContent content = oldContentAsIContentList.FirstOrDefault(x => x.Id == item.Id) ?? ApplicationContext.Services.ContentService.CreateContent(item.Name, ParentId, "YourContentType");

    // Update content
    content.Name = item.Name;
    content.SetValue("Attribute1", item.Attribute1);        
    finalContentList.Add(content);

    // The following code is required
    content.ChangePublishedState(PublishedState.Published);
    content.SortOrder = 1;
}

// if the finalContentList has some items, call the Sort method to commit and publish the changes
ApplicationContext.Services.ContentService.Sort(finalContentList);