mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-07-31 21:41:40 +08:00
Implementing eager fetching for Hql queries
This commit is contained in:
parent
840975e6b4
commit
1235f226d3
@ -130,6 +130,8 @@
|
||||
<Compile Include="Models\NavigationQueryPart.cs" />
|
||||
<Compile Include="Models\NavigationQueryPartRecord.cs" />
|
||||
<Compile Include="Models\QueryPart.cs" />
|
||||
<Compile Include="Providers\Filters\ContentPartsForm.cs" />
|
||||
<Compile Include="Providers\Filters\EagerFetchFilter.cs" />
|
||||
<Compile Include="Providers\Layouts\RawLayout.cs" />
|
||||
<Compile Include="Providers\Layouts\RawLayoutForms.cs" />
|
||||
<Compile Include="Providers\Layouts\RawShapes.cs" />
|
||||
|
@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.DisplayManagement;
|
||||
using Orchard.Forms.Services;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.Projections.Providers.Filters {
|
||||
public class ContentPartsForm : IFormProvider {
|
||||
private readonly IContentDefinitionManager _contentDefinitionManager;
|
||||
protected dynamic Shape { get; set; }
|
||||
public Localizer T { get; set; }
|
||||
|
||||
public ContentPartsForm(
|
||||
IShapeFactory shapeFactory,
|
||||
IContentDefinitionManager contentDefinitionManager) {
|
||||
_contentDefinitionManager = contentDefinitionManager;
|
||||
Shape = shapeFactory;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public void Describe(DescribeContext context) {
|
||||
Func<IShapeFactory, object> form =
|
||||
shape => {
|
||||
|
||||
var f = Shape.Form(
|
||||
Id: "AnyOfContentParts",
|
||||
_Parts: Shape.SelectList(
|
||||
Id: "contentparts", Name: "ContentParts",
|
||||
Title: T("Content parts"),
|
||||
Description: T("Select some content parts."),
|
||||
Size: 10,
|
||||
Multiple: true
|
||||
)
|
||||
);
|
||||
|
||||
f._Parts.Add(new SelectListItem { Value = "", Text = T("Any").Text });
|
||||
|
||||
foreach (var contentPart in _contentDefinitionManager.ListPartDefinitions().OrderBy(x => x.Name)) {
|
||||
f._Parts.Add(new SelectListItem { Value = contentPart.Name, Text = contentPart.Name });
|
||||
}
|
||||
|
||||
return f;
|
||||
};
|
||||
|
||||
context.Form("ContentPartsForm", form);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Projections.Descriptors.Filter;
|
||||
using IFilterProvider = Orchard.Projections.Services.IFilterProvider;
|
||||
|
||||
namespace Orchard.Projections.Providers.Filters {
|
||||
public class EagerFectchFilter : IFilterProvider {
|
||||
public EagerFectchFilter() {
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
|
||||
public void Describe(DescribeFilterContext describe) {
|
||||
describe.For("Content", T("Content"),T("Content"))
|
||||
.Element("EagerFetch", T("Eager fetch"), T("Eager fetch content parts"),
|
||||
ApplyFilter,
|
||||
DisplayFilter,
|
||||
"ContentPartsForm"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
public void ApplyFilter(FilterContext context) {
|
||||
var contentPartNames = (string)context.State.ContentParts;
|
||||
if (!String.IsNullOrEmpty(contentPartNames)) {
|
||||
var contentParts = contentPartNames.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
context.Query = context.Query.Include(contentParts);
|
||||
}
|
||||
}
|
||||
|
||||
public LocalizedString DisplayFilter(FilterContext context) {
|
||||
string contentparts = context.State.ContentParts;
|
||||
|
||||
if (String.IsNullOrEmpty(contentparts)) {
|
||||
return T("No content part");
|
||||
}
|
||||
|
||||
return T("Eager fetch parts {0}", contentparts);
|
||||
}
|
||||
}
|
||||
}
|
@ -18,14 +18,14 @@ namespace Orchard.ContentManagement {
|
||||
private readonly IEnumerable<ISqlStatementProvider> _sqlStatementProviders;
|
||||
private readonly ShellSettings _shellSettings;
|
||||
private VersionOptions _versionOptions;
|
||||
private string[] _includedPartNames = new string[0];
|
||||
private bool _cacheable;
|
||||
|
||||
protected IJoin _from;
|
||||
protected readonly List<Tuple<IAlias, Join>> _joins = new List<Tuple<IAlias, Join>>();
|
||||
protected readonly List<Tuple<IAlias, Action<IHqlExpressionFactory>>> _wheres = new List<Tuple<IAlias, Action<IHqlExpressionFactory>>>();
|
||||
protected readonly List<Tuple<IAlias, Action<IHqlSortFactory>>> _sortings = new List<Tuple<IAlias, Action<IHqlSortFactory>>>();
|
||||
|
||||
private bool cacheable;
|
||||
|
||||
public IContentManager ContentManager { get; private set; }
|
||||
|
||||
public DefaultHqlQuery(
|
||||
@ -74,13 +74,18 @@ namespace Orchard.ContentManagement {
|
||||
return BindCriteriaByAlias(BindItemCriteria(), "ContentType", "ct");
|
||||
}
|
||||
|
||||
internal IAlias BindItemCriteria() {
|
||||
internal IAlias BindItemCriteria(string type = "") {
|
||||
// [ContentItemVersionRecord] >join> [ContentItemRecord]
|
||||
return BindCriteriaByAlias(BindItemVersionCriteria(), typeof(ContentItemRecord).Name, "ci");
|
||||
return BindCriteriaByAlias(BindItemVersionCriteria(type), typeof(ContentItemRecord).Name, "ci");
|
||||
}
|
||||
|
||||
internal IAlias BindItemVersionCriteria() {
|
||||
return _from ?? (_from = new Join(typeof(ContentItemVersionRecord).FullName, "civ", ""));
|
||||
internal IAlias BindItemVersionCriteria(string type = "") {
|
||||
_from = _from ?? new Join(typeof(ContentItemVersionRecord).FullName, "civ", type);
|
||||
if (_from.Type.Length < type.Length) {
|
||||
_from.Type = type;
|
||||
}
|
||||
|
||||
return _from;
|
||||
}
|
||||
|
||||
internal IAlias BindPartCriteria<TRecord>() where TRecord : ContentPartRecord {
|
||||
@ -152,6 +157,12 @@ namespace Orchard.ContentManagement {
|
||||
if (contentTypeNames != null && contentTypeNames.Length != 0) {
|
||||
Where(BindTypeCriteria(), x => x.InG("Name", contentTypeNames));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public IHqlQuery Include(params string[] partNames) {
|
||||
_includedPartNames = _includedPartNames.Union(partNames).ToArray();
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -170,13 +181,13 @@ namespace Orchard.ContentManagement {
|
||||
|
||||
public IEnumerable<ContentItem> Slice(int skip, int count) {
|
||||
ApplyHqlVersionOptionsRestrictions(_versionOptions);
|
||||
cacheable = true;
|
||||
_cacheable = true;
|
||||
|
||||
var hql = ToHql(false);
|
||||
|
||||
var query = _session
|
||||
.CreateQuery(hql)
|
||||
.SetCacheable(cacheable)
|
||||
.SetCacheable(_cacheable)
|
||||
;
|
||||
|
||||
if (skip != 0) {
|
||||
@ -191,7 +202,9 @@ namespace Orchard.ContentManagement {
|
||||
.List<IDictionary>()
|
||||
.Select(x => (int)x["Id"]);
|
||||
|
||||
return ContentManager.GetManyByVersionId(ids, QueryHints.Empty);
|
||||
var contentPartRecords = _includedPartNames.Select(part => part + "Record").ToList();
|
||||
|
||||
return ContentManager.GetManyByVersionId(ids, new QueryHints().ExpandRecords(contentPartRecords));
|
||||
}
|
||||
|
||||
public int Count() {
|
||||
@ -224,7 +237,7 @@ namespace Orchard.ContentManagement {
|
||||
}
|
||||
else {
|
||||
// select distinct can't be used with newid()
|
||||
cacheable = false;
|
||||
_cacheable = false;
|
||||
sb.Replace("select distinct", "select ");
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,11 @@ namespace Orchard.ContentManagement {
|
||||
/// Add content type constraints to the query.
|
||||
/// </summary>
|
||||
IHqlQuery ForType(params string[] contentTypes);
|
||||
|
||||
/// <summary>
|
||||
/// Eagerly fetches specific content parts.
|
||||
/// </summary>
|
||||
IHqlQuery Include(params string[] contentParts);
|
||||
|
||||
/// <summary>
|
||||
/// Adds versioning options to the query.
|
||||
|
Loading…
Reference in New Issue
Block a user