mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
Support for query hints on IContentQuery<TPart>.
This commit is contained in:
@@ -63,7 +63,6 @@ namespace Orchard.ContentManagement {
|
|||||||
return BindCriteriaByPath(BindItemCriteria(), typeof(TRecord).Name);
|
return BindCriteriaByPath(BindItemCriteria(), typeof(TRecord).Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void ForType(params string[] contentTypeNames) {
|
private void ForType(params string[] contentTypeNames) {
|
||||||
if (contentTypeNames != null && contentTypeNames.Length != 0)
|
if (contentTypeNames != null && contentTypeNames.Length != 0)
|
||||||
// don't use the IN operator if not needed for performance reasons
|
// don't use the IN operator if not needed for performance reasons
|
||||||
@@ -174,6 +173,57 @@ namespace Orchard.ContentManagement {
|
|||||||
return criteria.SetProjection(Projections.RowCount()).UniqueResult<Int32>();
|
return criteria.SetProjection(Projections.RowCount()).UniqueResult<Int32>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WithQueryHints(QueryHints hints) {
|
||||||
|
if (hints == QueryHints.Empty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var contentItemVersionCriteria = BindItemVersionCriteria();
|
||||||
|
var contentItemCriteria = BindItemCriteria();
|
||||||
|
|
||||||
|
var contentItemMetadata = _session.SessionFactory.GetClassMetadata(typeof(ContentItemRecord));
|
||||||
|
var contentItemVersionMetadata = _session.SessionFactory.GetClassMetadata(typeof(ContentItemVersionRecord));
|
||||||
|
|
||||||
|
// break apart and group hints by their first segment
|
||||||
|
var hintDictionary = hints.Records
|
||||||
|
.Select(hint => new { Hint = hint, Segments = hint.Split('.') })
|
||||||
|
.GroupBy(item => item.Segments.FirstOrDefault())
|
||||||
|
.ToDictionary(grouping => grouping.Key, StringComparer.InvariantCultureIgnoreCase);
|
||||||
|
|
||||||
|
// locate hints that match properties in the ContentItemVersionRecord
|
||||||
|
foreach (var hit in contentItemVersionMetadata.PropertyNames.Where(hintDictionary.ContainsKey).SelectMany(key => hintDictionary[key])) {
|
||||||
|
contentItemVersionCriteria.SetFetchMode(hit.Hint, FetchMode.Eager);
|
||||||
|
hit.Segments.Take(hit.Segments.Count() - 1).Aggregate(contentItemVersionCriteria, ExtendCriteria);
|
||||||
|
}
|
||||||
|
|
||||||
|
// locate hints that match properties in the ContentItemRecord
|
||||||
|
foreach (var hit in contentItemMetadata.PropertyNames.Where(hintDictionary.ContainsKey).SelectMany(key => hintDictionary[key])) {
|
||||||
|
contentItemVersionCriteria.SetFetchMode("ContentItemRecord." + hit.Hint, FetchMode.Eager);
|
||||||
|
hit.Segments.Take(hit.Segments.Count() - 1).Aggregate(contentItemCriteria, ExtendCriteria);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hintDictionary.SelectMany(x => x.Value).Any(x => x.Segments.Count() > 1))
|
||||||
|
contentItemVersionCriteria.SetResultTransformer(new DistinctRootEntityResultTransformer());
|
||||||
|
}
|
||||||
|
|
||||||
|
void WithQueryHintsFor(string contentType) {
|
||||||
|
var contentItem = ContentManager.New(contentType);
|
||||||
|
var contentPartRecords = new List<string>();
|
||||||
|
foreach (var part in contentItem.Parts) {
|
||||||
|
var partType = part.GetType().BaseType;
|
||||||
|
if (partType.IsGenericType && partType.GetGenericTypeDefinition() == typeof(ContentPart<>)) {
|
||||||
|
var recordType = partType.GetGenericArguments().Single();
|
||||||
|
contentPartRecords.Add(recordType.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WithQueryHints(new QueryHints().ExpandRecords(contentPartRecords));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ICriteria ExtendCriteria(ICriteria criteria, string segment) {
|
||||||
|
return criteria.GetCriteriaByPath(segment) ?? criteria.CreateCriteria(segment, JoinType.LeftOuterJoin);
|
||||||
|
}
|
||||||
|
|
||||||
IContentQuery<TPart> IContentQuery.ForPart<TPart>() {
|
IContentQuery<TPart> IContentQuery.ForPart<TPart>() {
|
||||||
return new ContentQuery<TPart>(this);
|
return new ContentQuery<TPart>(this);
|
||||||
}
|
}
|
||||||
@@ -239,6 +289,16 @@ namespace Orchard.ContentManagement {
|
|||||||
_query.OrderByDescending(keySelector);
|
_query.OrderByDescending(keySelector);
|
||||||
return new ContentQuery<T, TRecord>(_query);
|
return new ContentQuery<T, TRecord>(_query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IContentQuery<T> IContentQuery<T>.WithQueryHints(QueryHints hints) {
|
||||||
|
_query.WithQueryHints(hints);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
IContentQuery<T> IContentQuery<T>.WithQueryHintsFor(string contentType) {
|
||||||
|
_query.WithQueryHintsFor(contentType);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -269,58 +329,14 @@ namespace Orchard.ContentManagement {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IContentQuery<T, TR> IContentQuery<T, TR>.WithQueryHints(QueryHints hints) {
|
||||||
public IContentQuery<T, TR> WithQueryHints(QueryHints hints) {
|
_query.WithQueryHints(hints);
|
||||||
if (hints == QueryHints.Empty) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
var contentItemVersionCriteria = _query.BindItemVersionCriteria();
|
|
||||||
var contentItemCriteria = _query.BindItemCriteria();
|
|
||||||
|
|
||||||
var contentItemMetadata = _query._session.SessionFactory.GetClassMetadata(typeof(ContentItemRecord));
|
|
||||||
var contentItemVersionMetadata = _query._session.SessionFactory.GetClassMetadata(typeof(ContentItemVersionRecord));
|
|
||||||
|
|
||||||
// break apart and group hints by their first segment
|
|
||||||
var hintDictionary = hints.Records
|
|
||||||
.Select(hint => new { Hint = hint, Segments = hint.Split('.') })
|
|
||||||
.GroupBy(item => item.Segments.FirstOrDefault())
|
|
||||||
.ToDictionary(grouping => grouping.Key, StringComparer.InvariantCultureIgnoreCase);
|
|
||||||
|
|
||||||
// locate hints that match properties in the ContentItemVersionRecord
|
|
||||||
foreach (var hit in contentItemVersionMetadata.PropertyNames.Where(hintDictionary.ContainsKey).SelectMany(key => hintDictionary[key])) {
|
|
||||||
contentItemVersionCriteria.SetFetchMode(hit.Hint, FetchMode.Eager);
|
|
||||||
hit.Segments.Take(hit.Segments.Count() - 1).Aggregate(contentItemVersionCriteria, ExtendCriteria);
|
|
||||||
}
|
|
||||||
|
|
||||||
// locate hints that match properties in the ContentItemRecord
|
|
||||||
foreach (var hit in contentItemMetadata.PropertyNames.Where(hintDictionary.ContainsKey).SelectMany(key => hintDictionary[key])) {
|
|
||||||
contentItemVersionCriteria.SetFetchMode("ContentItemRecord." + hit.Hint, FetchMode.Eager);
|
|
||||||
hit.Segments.Take(hit.Segments.Count() - 1).Aggregate(contentItemCriteria, ExtendCriteria);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hintDictionary.SelectMany(x => x.Value).Any(x => x.Segments.Count() > 1))
|
|
||||||
contentItemVersionCriteria.SetResultTransformer(new DistinctRootEntityResultTransformer());
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ICriteria ExtendCriteria(ICriteria criteria, string segment) {
|
IContentQuery<T, TR> IContentQuery<T, TR>.WithQueryHintsFor(string contentType) {
|
||||||
return criteria.GetCriteriaByPath(segment) ?? criteria.CreateCriteria(segment, JoinType.LeftOuterJoin);
|
_query.WithQueryHintsFor(contentType);
|
||||||
}
|
return this;
|
||||||
|
|
||||||
public IContentQuery<T, TR> WithQueryHintsFor(string contentType) {
|
|
||||||
var contentItem = _query.ContentManager.New(contentType);
|
|
||||||
var contentPartRecords = new List<string>();
|
|
||||||
foreach (var part in contentItem.Parts) {
|
|
||||||
var partType = part.GetType().BaseType;
|
|
||||||
if (partType.IsGenericType && partType.GetGenericTypeDefinition() == typeof(ContentPart<>)) {
|
|
||||||
var recordType = partType.GetGenericArguments().Single();
|
|
||||||
contentPartRecords.Add(recordType.Name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return WithQueryHints(new QueryHints().ExpandRecords(contentPartRecords));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ namespace Orchard.ContentManagement {
|
|||||||
IContentQuery<TPart, TRecord> Where<TRecord>(Expression<Func<TRecord, bool>> predicate) where TRecord : ContentPartRecord;
|
IContentQuery<TPart, TRecord> Where<TRecord>(Expression<Func<TRecord, bool>> predicate) where TRecord : ContentPartRecord;
|
||||||
IContentQuery<TPart, TRecord> OrderBy<TRecord>(Expression<Func<TRecord, object>> keySelector) where TRecord : ContentPartRecord;
|
IContentQuery<TPart, TRecord> OrderBy<TRecord>(Expression<Func<TRecord, object>> keySelector) where TRecord : ContentPartRecord;
|
||||||
IContentQuery<TPart, TRecord> OrderByDescending<TRecord>(Expression<Func<TRecord, object>> keySelector) where TRecord : ContentPartRecord;
|
IContentQuery<TPart, TRecord> OrderByDescending<TRecord>(Expression<Func<TRecord, object>> keySelector) where TRecord : ContentPartRecord;
|
||||||
|
|
||||||
|
IContentQuery<TPart> WithQueryHints(QueryHints hints);
|
||||||
|
IContentQuery<TPart> WithQueryHintsFor(string contentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IContentQuery<TPart, TRecord> : IContentQuery<TPart> where TPart : IContent where TRecord : ContentPartRecord {
|
public interface IContentQuery<TPart, TRecord> : IContentQuery<TPart> where TPart : IContent where TRecord : ContentPartRecord {
|
||||||
|
|||||||
Reference in New Issue
Block a user