Perf: lazy-loading more information which is used infrequently

site id is cached for SiteService.GetSiteSettings performance
HasComments part loads collections on demand
HasTags part loads collections on demand

--HG--
branch : dev
This commit is contained in:
Louis DeJardin
2010-05-16 19:47:51 -07:00
parent 98c1d931e0
commit 48be8159b9
5 changed files with 72 additions and 50 deletions

View File

@@ -1,6 +1,7 @@
using System;
using System.Linq;
using JetBrains.Annotations;
using Orchard.Caching;
using Orchard.Core.Settings.Models;
using Orchard.Data;
using Orchard.Logging;
@@ -10,30 +11,38 @@ using Orchard.Settings;
namespace Orchard.Core.Settings.Services {
[UsedImplicitly]
public class SiteService : ISiteService {
private readonly IRepository<SiteSettingsRecord> _siteSettingsRepository;
private readonly IContentManager _contentManager;
private readonly ICacheManager _cacheManager;
public SiteService(IRepository<SiteSettingsRecord> siteSettingsRepository, IContentManager contentManager) {
_siteSettingsRepository = siteSettingsRepository;
public SiteService(
IRepository<SiteSettingsRecord> siteSettingsRepository,
IContentManager contentManager,
ICacheManager cacheManager) {
_contentManager = contentManager;
_cacheManager = cacheManager;
Logger = NullLogger.Instance;
}
public ILogger Logger { get; set; }
public ISite GetSiteSettings() {
SiteSettingsRecord record = _siteSettingsRepository.Table.FirstOrDefault();
if (record == null) {
ISite site = _contentManager.Create<SiteSettings>("site", item => {
item.Record.SiteSalt = Guid.NewGuid().ToString("N");
item.Record.SiteName = "My Orchard Project Application";
item.Record.PageTitleSeparator = " - ";
});
// ensure subsequent calls will locate this object
_contentManager.Flush();
return site;
}
return _contentManager.Get<ISite>(record.Id);
var siteId = _cacheManager.Get("SiteId", ctx => {
var site = _contentManager.Query("site")
.Slice(0, 1)
.FirstOrDefault();
if (site == null) {
site = _contentManager.Create<SiteSettings>("site", item => {
item.Record.SiteSalt = Guid.NewGuid().ToString("N");
item.Record.SiteName = "My Orchard Project Application";
item.Record.PageTitleSeparator = " - ";
}).ContentItem;
}
return site.Id;
});
return _contentManager.Get<ISite>(siteId);
}
}
}

View File

@@ -20,23 +20,21 @@ namespace Orchard.Comments.Handlers {
Filters.Add(StorageFilter.For(hasCommentsRepository));
OnActivated<HasComments>((ctx, x) => {
x.CommentsActive = true;
x.CommentsShown = true;
});
x.CommentsActive = true;
x.CommentsShown = true;
});
OnLoading<HasComments>((context, comments) => {
//TODO: lazy loading?
comments.Comments = contentManager
.Query<Comment, CommentRecord>()
.Where(x => x.CommentedOn == context.ContentItem.Id && x.Status == CommentStatus.Approved)
.List().ToList();
comments._comments.Loader(list => contentManager
.Query<Comment, CommentRecord>()
.Where(x => x.CommentedOn == context.ContentItem.Id && x.Status == CommentStatus.Approved)
.List().ToList());
//TODO: lazy loading?
comments.PendingComments = contentManager
.Query<Comment, CommentRecord>()
.Where(x => x.CommentedOn == context.ContentItem.Id && x.Status == CommentStatus.Pending)
.List().ToList();
});
comments._pendingComments.Loader(list => contentManager
.Query<Comment, CommentRecord>()
.Where(x => x.CommentedOn == context.ContentItem.Id && x.Status == CommentStatus.Pending)
.List().ToList());
});
OnRemoved<HasComments>(
(context, c) => {

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Utilities;
namespace Orchard.Comments.Models {
public class HasComments : ContentPart<HasCommentsRecord> {
@@ -8,8 +9,11 @@ namespace Orchard.Comments.Models {
PendingComments = new List<Comment>();
}
public IList<Comment> Comments { get; set; }
public IList<Comment> PendingComments { get; set; }
public readonly LazyField<IList<Comment>> _comments = new LazyField<IList<Comment>>();
public readonly LazyField<IList<Comment>> _pendingComments = new LazyField<IList<Comment>>();
public IList<Comment> Comments { get { return _comments.Value; } set { _comments.Value = value; } }
public IList<Comment> PendingComments { get { return _pendingComments.Value; } set { _pendingComments.Value = value; } }
public bool CommentsShown {
get { return Record.CommentsShown; }

View File

@@ -14,26 +14,33 @@ namespace Orchard.Tags.Handlers {
Filters.Add(new ActivatingFilter<HasTags>("blogpost"));
Filters.Add(new ActivatingFilter<HasTags>("page"));
OnLoading<HasTags>((context, ht) => {
HasTags tags = context.ContentItem.As<HasTags>();
tags.AllTags = tagsRepository.Table.ToList();
IEnumerable<TagsContentItems> tagsContentItems = tagsContentItemsRepository.Fetch(x => x.ContentItemId == context.ContentItem.Id);
foreach (var tagContentItem in tagsContentItems) {
Tag tag = tagsRepository.Get(tagContentItem.TagId);
tags.CurrentTags.Add(tag);
}
});
OnLoading<HasTags>((context, tags) => {
// provide names of all tags on demand
tags._allTags.Loader(list => tagsRepository.Table.ToList());
// populate list of attached tags on demand
tags._currentTags.Loader(list => {
var tagsContentItems = tagsContentItemsRepository.Fetch(x => x.ContentItemId == context.ContentItem.Id);
foreach (var tagContentItem in tagsContentItems) {
var tag = tagsRepository.Get(tagContentItem.TagId);
list.Add(tag);
}
return list;
});
});
OnRemoved<HasTags>((context, ht) => {
tagsContentItemsRepository.Flush();
tagsContentItemsRepository.Flush();
HasTags tags = context.ContentItem.As<HasTags>();
foreach (var tag in tags.CurrentTags) {
if (!tagsContentItemsRepository.Fetch(x => x.ContentItemId == context.ContentItem.Id).Any()) {
tagsRepository.Delete(tag);
}
}
});
HasTags tags = context.ContentItem.As<HasTags>();
foreach (var tag in tags.CurrentTags) {
if (!tagsContentItemsRepository.Fetch(x => x.ContentItemId == context.ContentItem.Id).Any()) {
tagsRepository.Delete(tag);
}
}
});
}
}
}

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Utilities;
namespace Orchard.Tags.Models {
public class HasTags : ContentPart {
@@ -8,7 +9,10 @@ namespace Orchard.Tags.Models {
CurrentTags = new List<Tag>();
}
public IList<Tag> AllTags { get; set; }
public IList<Tag> CurrentTags { get; set; }
public readonly LazyField<IList<Tag>> _allTags = new LazyField<IList<Tag>>();
public readonly LazyField<IList<Tag>> _currentTags = new LazyField<IList<Tag>>();
public IList<Tag> AllTags { get { return _allTags.Value; } set { _allTags.Value = value; } }
public IList<Tag> CurrentTags { get { return _currentTags.Value; } set { _currentTags.Value = value; } }
}
}