mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-11-24 08:46:48 +08:00
Perf: content manager improvements
Adding adding content manager session to hold items which have been loaded during a request Altering the routine that determines which version of an item is needed to favor the inmemory collection over direct query where possible --HG-- branch : dev
This commit is contained in:
@@ -13,3 +13,4 @@ glob:src/Orchard.Web/Media/*
|
||||
glob:desktop.ini
|
||||
glob:src/Orchard.Azure.suo
|
||||
glob:log.xml
|
||||
glob:profiling
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Autofac;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
@@ -12,16 +13,19 @@ namespace Orchard.ContentManagement {
|
||||
private readonly IRepository<ContentTypeRecord> _contentTypeRepository;
|
||||
private readonly IRepository<ContentItemRecord> _contentItemRepository;
|
||||
private readonly IRepository<ContentItemVersionRecord> _contentItemVersionRepository;
|
||||
private readonly Func<IContentManagerSession> _contentManagerSession;
|
||||
|
||||
public DefaultContentManager(
|
||||
IComponentContext context,
|
||||
IRepository<ContentTypeRecord> contentTypeRepository,
|
||||
IRepository<ContentItemRecord> contentItemRepository,
|
||||
IRepository<ContentItemVersionRecord> contentItemVersionRepository) {
|
||||
IRepository<ContentItemVersionRecord> contentItemVersionRepository,
|
||||
Func<IContentManagerSession> contentManagerSession) {
|
||||
_context = context;
|
||||
_contentTypeRepository = contentTypeRepository;
|
||||
_contentItemRepository = contentItemRepository;
|
||||
_contentItemVersionRepository = contentItemVersionRepository;
|
||||
_contentManagerSession = contentManagerSession;
|
||||
}
|
||||
|
||||
private IEnumerable<IContentHandler> _handlers;
|
||||
@@ -72,45 +76,24 @@ namespace Orchard.ContentManagement {
|
||||
}
|
||||
|
||||
public virtual ContentItem Get(int id, VersionOptions options) {
|
||||
var session = _contentManagerSession();
|
||||
ContentItem contentItem;
|
||||
|
||||
ContentItemVersionRecord versionRecord = null;
|
||||
var appendLatestVersion = false;
|
||||
|
||||
// obtain the root records based on version options
|
||||
if (options.VersionRecordId != 0) {
|
||||
// explicit version record known
|
||||
// short-circuit if item held in session
|
||||
if (session.RecallVersionRecordId(options.VersionRecordId, out contentItem))
|
||||
return contentItem;
|
||||
|
||||
// locate explicit version record
|
||||
versionRecord = _contentItemVersionRepository.Get(options.VersionRecordId);
|
||||
}
|
||||
else {
|
||||
// FIX: rework this so it falls back to an in-memory scan when the results don't fit the criteria
|
||||
var record = _contentItemRepository.Get(id);
|
||||
if (options.IsPublished) {
|
||||
versionRecord = _contentItemVersionRepository.Get(x => x.ContentItemRecord == record && x.Published);
|
||||
}
|
||||
else if (options.IsLatest) {
|
||||
versionRecord = _contentItemVersionRepository.Get(x => x.ContentItemRecord == record && x.Latest);
|
||||
}
|
||||
else if (options.IsDraft || options.IsDraftRequired) {
|
||||
versionRecord = _contentItemVersionRepository.Get(x => x.ContentItemRecord == record && x.Latest && !x.Published);
|
||||
if (versionRecord == null && options.IsDraftRequired) {
|
||||
versionRecord = _contentItemVersionRepository.Get(x => x.ContentItemRecord == record && x.Latest);
|
||||
appendLatestVersion = true;
|
||||
}
|
||||
}
|
||||
else if (options.VersionNumber != 0) {
|
||||
versionRecord = _contentItemVersionRepository.Get(x => x.ContentItemRecord == record && x.Number == options.VersionNumber);
|
||||
}
|
||||
|
||||
//TEMP: this is to transition people with old databases
|
||||
if (versionRecord == null && record != null && !record.Versions.Any() && options.IsPublished) {
|
||||
versionRecord = new ContentItemVersionRecord {
|
||||
ContentItemRecord = record,
|
||||
Latest = true,
|
||||
Published = true,
|
||||
Number = 1
|
||||
};
|
||||
record.Versions.Add(versionRecord);
|
||||
_contentItemVersionRepository.Create(versionRecord);
|
||||
}
|
||||
if (record != null)
|
||||
versionRecord = GetVersionRecord(options, record);
|
||||
}
|
||||
|
||||
// no record means content item doesn't exist
|
||||
@@ -118,10 +101,19 @@ namespace Orchard.ContentManagement {
|
||||
return null;
|
||||
}
|
||||
|
||||
// return item if obtained earlier in session
|
||||
if (session.RecallVersionRecordId(versionRecord.Id, out contentItem)) {
|
||||
return contentItem;
|
||||
}
|
||||
|
||||
|
||||
// allocate instance and set record property
|
||||
var contentItem = New(versionRecord.ContentItemRecord.ContentType.Name);
|
||||
contentItem = New(versionRecord.ContentItemRecord.ContentType.Name);
|
||||
contentItem.VersionRecord = versionRecord;
|
||||
|
||||
// store in session prior to loading to avoid some problems with simple circular dependencies
|
||||
session.Store(contentItem);
|
||||
|
||||
// create a context with a new instance to load
|
||||
var context = new LoadContentContext(contentItem);
|
||||
|
||||
@@ -133,14 +125,42 @@ namespace Orchard.ContentManagement {
|
||||
handler.Loaded(context);
|
||||
}
|
||||
|
||||
// when draft is required and not currently available a new version is appended
|
||||
if (appendLatestVersion) {
|
||||
// when draft is required and latest is published a new version is appended
|
||||
if (options.IsDraftRequired && versionRecord.Published) {
|
||||
return BuildNewVersion(context.ContentItem);
|
||||
}
|
||||
|
||||
return context.ContentItem;
|
||||
}
|
||||
|
||||
private ContentItemVersionRecord GetVersionRecord(VersionOptions options, ContentItemRecord itemRecord) {
|
||||
if (options.IsPublished) {
|
||||
return itemRecord.Versions.FirstOrDefault(
|
||||
x => x.Published) ??
|
||||
_contentItemVersionRepository.Get(
|
||||
x => x.ContentItemRecord == itemRecord && x.Published);
|
||||
}
|
||||
if (options.IsLatest || options.IsDraftRequired) {
|
||||
return itemRecord.Versions.FirstOrDefault(
|
||||
x => x.Latest) ??
|
||||
_contentItemVersionRepository.Get(
|
||||
x => x.ContentItemRecord == itemRecord && x.Latest);
|
||||
}
|
||||
if (options.IsDraft) {
|
||||
return itemRecord.Versions.FirstOrDefault(
|
||||
x => x.Latest && !x.Published) ??
|
||||
_contentItemVersionRepository.Get(
|
||||
x => x.ContentItemRecord == itemRecord && x.Latest && !x.Published);
|
||||
}
|
||||
if (options.VersionNumber != 0) {
|
||||
return itemRecord.Versions.FirstOrDefault(
|
||||
x => x.Number == options.VersionNumber) ??
|
||||
_contentItemVersionRepository.Get(
|
||||
x => x.ContentItemRecord == itemRecord && x.Number == options.VersionNumber);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual IEnumerable<ContentItem> GetAllVersions(int id) {
|
||||
return _contentItemVersionRepository
|
||||
.Fetch(x => x.ContentItemRecord.Id == id)
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.ContentManagement {
|
||||
public class DefaultContentManagerSession : IContentManagerSession {
|
||||
private readonly IDictionary<int, ContentItem> _itemByVersionRecordId = new Dictionary<int, ContentItem>();
|
||||
|
||||
public void Store(ContentItem item) {
|
||||
_itemByVersionRecordId.Add(item.VersionRecord.Id, item);
|
||||
}
|
||||
|
||||
public bool RecallVersionRecordId(int id, out ContentItem item) {
|
||||
return _itemByVersionRecordId.TryGetValue(id, out item);
|
||||
}
|
||||
}
|
||||
}
|
||||
6
src/Orchard/ContentManagement/IContentManagerSession.cs
Normal file
6
src/Orchard/ContentManagement/IContentManagerSession.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Orchard.ContentManagement {
|
||||
public interface IContentManagerSession : IDependency {
|
||||
void Store(ContentItem item);
|
||||
bool RecallVersionRecordId(int id, out ContentItem item);
|
||||
}
|
||||
}
|
||||
@@ -150,6 +150,8 @@
|
||||
<Compile Include="Caching\DefaultCacheManager.cs" />
|
||||
<Compile Include="Caching\ICacheHolder.cs" />
|
||||
<Compile Include="Caching\Weak.cs" />
|
||||
<Compile Include="ContentManagement\DefaultContentManagerSession.cs" />
|
||||
<Compile Include="ContentManagement\IContentManagerSession.cs" />
|
||||
<Compile Include="FileSystems\WebSite\WebSiteFolder.cs" />
|
||||
<Compile Include="FileSystems\AppData\IAppDataFolder.cs" />
|
||||
<Compile Include="FileSystems\WebSite\IWebSiteFolder.cs" />
|
||||
|
||||
Reference in New Issue
Block a user