我有一个评论类型结构,用户可以在其中发布对文章的回复。 (一篇文章可以有很多讨论回复)。当用户添加回复时,我希望父文章的上次更新日期也发生变化,以便在从前端查看时,文章被放置在列表的顶部,表明它已有最近的活动。为了实现这一点,评论是通过自定义控制器添加的,然后我使用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);
}
}
}
}
此代码是否有明显的问题导致性能问题?
非常感谢,
答案 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,那么您也可以使用相同的Umbraco
和Services
属性。
答案 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);