mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-08 00:14:31 +08:00
Using customized NHibernate.Linq libraries in DefaultContentQuery.
The NH3 implementation of Linq in Query Over is missing a great part of .NET, whereas the NHContrib version is better, but is not compatible with NH3. This is fixed by applying some updates to the original source code and using this custom assembly. --HG-- branch : 1.x
This commit is contained in:
281
lib/nhibernate.linq/DetachedCriteriaAdapter.cs
Normal file
281
lib/nhibernate.linq/DetachedCriteriaAdapter.cs
Normal file
@@ -0,0 +1,281 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NHibernate.Criterion;
|
||||
using NHibernate.SqlCommand;
|
||||
using NHibernate.Transform;
|
||||
|
||||
namespace NHibernate.Linq.Util
|
||||
{
|
||||
public static class DetachedCriteriaExtensions
|
||||
{
|
||||
public static ICriteria Adapt(this DetachedCriteria criteria, ISession session)
|
||||
{
|
||||
if (criteria == null) return null;
|
||||
return new DetachedCriteriaAdapter(criteria, session);
|
||||
}
|
||||
}
|
||||
|
||||
public class DetachedCriteriaAdapter : ICriteria
|
||||
{
|
||||
private readonly DetachedCriteria detachedCriteria;
|
||||
private readonly ISession session;
|
||||
|
||||
public DetachedCriteriaAdapter(DetachedCriteria detachedCriteria, ISession session)
|
||||
{
|
||||
this.detachedCriteria = detachedCriteria;
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
public DetachedCriteria DetachedCriteria
|
||||
{
|
||||
get { return detachedCriteria; }
|
||||
}
|
||||
|
||||
public ISession Session
|
||||
{
|
||||
get { return session; }
|
||||
}
|
||||
|
||||
#region ICriteria Members
|
||||
|
||||
public IProjection Projection
|
||||
{
|
||||
get
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public ICriteria Add(ICriterion expression)
|
||||
{
|
||||
return detachedCriteria.Add(expression).Adapt(session);
|
||||
}
|
||||
|
||||
public ICriteria AddOrder(Order order)
|
||||
{
|
||||
return detachedCriteria.AddOrder(order).Adapt(session);
|
||||
}
|
||||
|
||||
public string Alias
|
||||
{
|
||||
get { return detachedCriteria.Alias; }
|
||||
}
|
||||
|
||||
public void ClearOrderds()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public ICriteria CreateAlias(string associationPath, string alias, JoinType joinType)
|
||||
{
|
||||
return detachedCriteria.CreateAlias(associationPath, alias, joinType).Adapt(session);
|
||||
}
|
||||
|
||||
public ICriteria CreateAlias(string associationPath, string alias)
|
||||
{
|
||||
return detachedCriteria.CreateAlias(associationPath, alias).Adapt(session);
|
||||
}
|
||||
|
||||
public ICriteria CreateAlias(string associationPath, string alias, JoinType joinType, ICriterion withClause)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ICriteria CreateCriteria(string associationPath, string alias, JoinType joinType)
|
||||
{
|
||||
return detachedCriteria.CreateCriteria(associationPath, alias, joinType).Adapt(session);
|
||||
}
|
||||
|
||||
public ICriteria CreateCriteria(string associationPath, string alias)
|
||||
{
|
||||
return detachedCriteria.CreateCriteria(associationPath, alias).Adapt(session);
|
||||
}
|
||||
|
||||
public ICriteria CreateCriteria(string associationPath, JoinType joinType)
|
||||
{
|
||||
return detachedCriteria.CreateCriteria(associationPath, joinType).Adapt(session);
|
||||
}
|
||||
|
||||
public ICriteria CreateCriteria(string associationPath, string alias, JoinType joinType, ICriterion withClause)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ICriteria CreateCriteria(string associationPath)
|
||||
{
|
||||
return detachedCriteria.CreateCriteria(associationPath).Adapt(session);
|
||||
}
|
||||
|
||||
public ICriteria GetCriteriaByAlias(string alias)
|
||||
{
|
||||
return detachedCriteria.GetCriteriaByAlias(alias).Adapt(session);
|
||||
}
|
||||
|
||||
public ICriteria GetCriteriaByPath(string path)
|
||||
{
|
||||
return detachedCriteria.GetCriteriaByPath(path).Adapt(session);
|
||||
}
|
||||
|
||||
public IList<T> List<T>()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void List(IList results)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public IList List()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public ICriteria SetCacheMode(CacheMode cacheMode)
|
||||
{
|
||||
return detachedCriteria.SetCacheMode(cacheMode).Adapt(session);
|
||||
}
|
||||
|
||||
public ICriteria SetCacheRegion(string cacheRegion)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public ICriteria SetCacheable(bool cacheable)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public ICriteria SetComment(string comment)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public ICriteria SetFetchMode(string associationPath, FetchMode mode)
|
||||
{
|
||||
return detachedCriteria.SetFetchMode(associationPath, mode).Adapt(session);
|
||||
}
|
||||
|
||||
public ICriteria SetFetchSize(int fetchSize)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public ICriteria SetFirstResult(int firstResult)
|
||||
{
|
||||
return detachedCriteria.SetFirstResult(firstResult).Adapt(session);
|
||||
}
|
||||
|
||||
public ICriteria SetFlushMode(FlushMode flushMode)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public ICriteria SetLockMode(string alias, LockMode lockMode)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public ICriteria SetLockMode(LockMode lockMode)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public ICriteria SetMaxResults(int maxResults)
|
||||
{
|
||||
return detachedCriteria.SetMaxResults(maxResults).Adapt(session);
|
||||
}
|
||||
|
||||
public ICriteria SetProjection(IProjection projection)
|
||||
{
|
||||
return detachedCriteria.SetProjection(projection).Adapt(session);
|
||||
}
|
||||
|
||||
public ICriteria SetProjection(params IProjection[] projections)
|
||||
{
|
||||
var projectionList = Projections.ProjectionList();
|
||||
foreach (var proj in projections)
|
||||
projectionList.Add(proj);
|
||||
|
||||
return detachedCriteria.SetProjection(projectionList).Adapt(session);
|
||||
}
|
||||
|
||||
public ICriteria SetResultTransformer(IResultTransformer resultTransformer)
|
||||
{
|
||||
return detachedCriteria.SetResultTransformer(resultTransformer).Adapt(session);
|
||||
}
|
||||
|
||||
public ICriteria SetTimeout(int timeout)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public T UniqueResult<T>()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public object UniqueResult()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public System.Type GetRootEntityTypeIfAvailable()
|
||||
{
|
||||
return detachedCriteria.GetRootEntityTypeIfAvailable();
|
||||
}
|
||||
|
||||
public void ClearOrders()
|
||||
{
|
||||
detachedCriteria.ClearOrders();
|
||||
}
|
||||
|
||||
public IEnumerable<T> Future<T>()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public IFutureValue<T> FutureValue<T>()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ICloneable Members
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
private bool _readOnly;
|
||||
private bool _readOnlyInitialized;
|
||||
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
return _readOnly;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReadOnlyInitialized
|
||||
{
|
||||
get
|
||||
{
|
||||
return _readOnlyInitialized;
|
||||
}
|
||||
}
|
||||
|
||||
public ICriteria SetReadOnly(bool readOnly)
|
||||
{
|
||||
_readOnly = readOnly;
|
||||
_readOnlyInitialized = true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
BIN
lib/nhibernate.linq/NHibernate.Linq.dll
Normal file
BIN
lib/nhibernate.linq/NHibernate.Linq.dll
Normal file
Binary file not shown.
4
lib/nhibernate.linq/orchard-customizations.txt
Normal file
4
lib/nhibernate.linq/orchard-customizations.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
This library has been modified to be compatible with NH 3.3.
|
||||
The file DetachedCriteriaAdapter.cs in this folder is used instead of the original onw from soure code.
|
||||
|
||||
Source code can be found at http://sourceforge.net/projects/nhcontrib/files/NHibernate.Linq/1.0/NHibernate.Linq-1.0.0.GA-src.zip
|
@@ -16,8 +16,11 @@
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
|
||||
<bindingRedirect oldVersion="1.0.0.0" newVersion="3.0.0.0"/>
|
||||
<bindingRedirect oldVersion="2.0.0.0" newVersion="3.0.0.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="NHibernate" publicKeyToken="aa95f207798dfdb4" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.3.1.4000" newVersion="3.3.1.4000" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
@@ -132,7 +132,7 @@ namespace Orchard.Tags.Services {
|
||||
public IEnumerable<IContent> GetTaggedContentItems(int tagId, int skip, int take, VersionOptions options) {
|
||||
return _orchardServices.ContentManager
|
||||
.Query<TagsPart, TagsPartRecord>()
|
||||
.WhereAny(part => part.Tags, tag => tag.TagRecord.Id == tagId)
|
||||
.Where(tpr => tpr.Tags.Any(tr => tr.TagRecord.Id == tagId))
|
||||
.Join<CommonPartRecord>().OrderByDescending(x => x.CreatedUtc)
|
||||
.Slice(skip, take);
|
||||
}
|
||||
@@ -144,7 +144,7 @@ namespace Orchard.Tags.Services {
|
||||
public int GetTaggedContentItemCount(int tagId, VersionOptions options) {
|
||||
return _orchardServices.ContentManager
|
||||
.Query<TagsPart, TagsPartRecord>()
|
||||
.WhereAny(part => part.Tags, tag => tag.TagRecord.Id == tagId)
|
||||
.Where(tpr => tpr.Tags.Any(tr => tr.TagRecord.Id == tagId))
|
||||
.Count();
|
||||
}
|
||||
|
||||
|
@@ -34,9 +34,6 @@ namespace Orchard.ContentManagement {
|
||||
private const string Published = "Published";
|
||||
private const string Draft = "Draft";
|
||||
|
||||
static DefaultContentManager() {
|
||||
RestrictionExtensions.RegisterExtensions();
|
||||
}
|
||||
public DefaultContentManager(
|
||||
IComponentContext context,
|
||||
IRepository<ContentTypeRecord> contentTypeRepository,
|
||||
|
@@ -1,31 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection.Emit;
|
||||
using NHibernate;
|
||||
using NHibernate.Criterion;
|
||||
using NHibernate.Impl;
|
||||
using NHibernate.Linq;
|
||||
using Orchard.ContentManagement.Records;
|
||||
using Orchard.Data;
|
||||
using NHibernate.Transform;
|
||||
using NHibernate.SqlCommand;
|
||||
using Expression = System.Linq.Expressions.Expression;
|
||||
using Orchard.Utility.Extensions;
|
||||
|
||||
namespace Orchard.ContentManagement {
|
||||
public class DefaultContentQuery : IContentQuery {
|
||||
private readonly ISessionLocator _sessionLocator;
|
||||
private ISession _session;
|
||||
private IQueryOver<ContentItemVersionRecord, ContentItemVersionRecord> _itemVersionQueryOver;
|
||||
private readonly IDictionary<string, object> _joins;
|
||||
|
||||
private ICriteria _itemVersionCriteria;
|
||||
private VersionOptions _versionOptions;
|
||||
|
||||
public DefaultContentQuery(IContentManager contentManager, ISessionLocator sessionLocator) {
|
||||
_sessionLocator = sessionLocator;
|
||||
ContentManager = contentManager;
|
||||
|
||||
_joins = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
public IContentManager ContentManager { get; private set; }
|
||||
@@ -36,61 +32,41 @@ namespace Orchard.ContentManagement {
|
||||
return _session;
|
||||
}
|
||||
|
||||
IQueryOver<ContentItemVersionRecord, TRecord> BindQueryOverByPath<TRecord, TU>(IQueryOver<ContentItemVersionRecord, TU> queryOver, string name, JoinType joinType = JoinType.InnerJoin) {
|
||||
if (_joins.ContainsKey(typeof(TRecord).Name)) {
|
||||
return (IQueryOver<ContentItemVersionRecord, TRecord>)_joins[typeof(TRecord).Name];
|
||||
}
|
||||
|
||||
// public TPartRecord TPartRecord {get;set;}
|
||||
var dynamicMethod = new DynamicMethod(name, typeof(TRecord), null, typeof(TU));
|
||||
var syntheticMethod = new ContentItemAlteration.SyntheticMethodInfo(dynamicMethod, typeof(TU));
|
||||
var syntheticProperty = new ContentItemAlteration.SyntheticPropertyInfo(syntheticMethod);
|
||||
|
||||
// record => record.TPartRecord
|
||||
var parameter = Expression.Parameter(typeof(TU), "record");
|
||||
var syntheticExpression = (Expression<Func<TU, TRecord>>)Expression.Lambda(
|
||||
typeof(Func<TU, TRecord>),
|
||||
Expression.Property(parameter, syntheticProperty),
|
||||
parameter);
|
||||
|
||||
var join = queryOver.JoinQueryOver(syntheticExpression, joinType);
|
||||
_joins[typeof(TRecord).Name] = join;
|
||||
|
||||
return join;
|
||||
ICriteria BindCriteriaByPath(ICriteria criteria, string path) {
|
||||
return criteria.GetCriteriaByPath(path) ?? criteria.CreateCriteria(path);
|
||||
}
|
||||
|
||||
IQueryOver<ContentItemVersionRecord, ContentTypeRecord> BindTypeQueryOver() {
|
||||
ICriteria BindTypeCriteria() {
|
||||
// ([ContentItemVersionRecord] >join> [ContentItemRecord]) >join> [ContentType]
|
||||
|
||||
return BindQueryOverByPath<ContentTypeRecord, ContentItemRecord>(BindItemQueryOver(), "ContentType", JoinType.LeftOuterJoin);
|
||||
return BindCriteriaByPath(BindItemCriteria(), "ContentType");
|
||||
}
|
||||
|
||||
IQueryOver<ContentItemVersionRecord, ContentItemRecord> BindItemQueryOver() {
|
||||
ICriteria BindItemCriteria() {
|
||||
// [ContentItemVersionRecord] >join> [ContentItemRecord]
|
||||
|
||||
return BindQueryOverByPath<ContentItemRecord, ContentItemVersionRecord>(BindItemVersionQueryOver(), "ContentItemRecord", JoinType.LeftOuterJoin);
|
||||
return BindCriteriaByPath(BindItemVersionCriteria(), "ContentItemRecord");
|
||||
}
|
||||
|
||||
IQueryOver<ContentItemVersionRecord, ContentItemVersionRecord> BindItemVersionQueryOver() {
|
||||
if (_itemVersionQueryOver == null) {
|
||||
_itemVersionQueryOver = BindSession().QueryOver<ContentItemVersionRecord>();
|
||||
_itemVersionQueryOver.Cacheable();
|
||||
ICriteria BindItemVersionCriteria() {
|
||||
if (_itemVersionCriteria == null) {
|
||||
_itemVersionCriteria = BindSession().CreateCriteria<ContentItemVersionRecord>();
|
||||
_itemVersionCriteria.SetCacheable(true);
|
||||
}
|
||||
return _itemVersionQueryOver;
|
||||
return _itemVersionCriteria;
|
||||
}
|
||||
|
||||
IQueryOver<ContentItemVersionRecord, TRecord> BindPartQueryOver<TRecord>() where TRecord : ContentPartRecord {
|
||||
if (typeof (TRecord).IsSubclassOf(typeof (ContentPartVersionRecord))) {
|
||||
return BindQueryOverByPath<TRecord, ContentItemVersionRecord>(BindItemVersionQueryOver(), typeof(TRecord).Name);
|
||||
ICriteria BindPartCriteria<TRecord>() where TRecord : ContentPartRecord {
|
||||
if (typeof(TRecord).IsSubclassOf(typeof(ContentPartVersionRecord))) {
|
||||
return BindCriteriaByPath(BindItemVersionCriteria(), typeof(TRecord).Name);
|
||||
}
|
||||
|
||||
return BindQueryOverByPath<TRecord, ContentItemRecord>(BindItemQueryOver(), typeof(TRecord).Name);
|
||||
return BindCriteriaByPath(BindItemCriteria(), typeof(TRecord).Name);
|
||||
}
|
||||
|
||||
|
||||
private void ForType(params string[] contentTypeNames) {
|
||||
if (contentTypeNames != null && contentTypeNames.Length != 0)
|
||||
BindTypeQueryOver().Where(Restrictions.InG("Name", contentTypeNames));
|
||||
BindTypeCriteria().Add(Restrictions.InG("Name", contentTypeNames));
|
||||
}
|
||||
|
||||
public void ForVersion(VersionOptions options) {
|
||||
@@ -99,78 +75,86 @@ namespace Orchard.ContentManagement {
|
||||
|
||||
private void Where<TRecord>() where TRecord : ContentPartRecord {
|
||||
// this simply demands an inner join
|
||||
BindPartQueryOver<TRecord>();
|
||||
BindPartCriteria<TRecord>();
|
||||
}
|
||||
|
||||
private void Where<TRecord>(Expression<Func<TRecord, bool>> predicate) where TRecord : ContentPartRecord {
|
||||
var processedCriteria = NHibernate.Impl.ExpressionProcessor.ProcessExpression(predicate);
|
||||
BindPartQueryOver<TRecord>().Where(processedCriteria);
|
||||
//BindPartQueryOver<TRecord>().WithSubquery.WhereSome(.Where(predicate);
|
||||
}
|
||||
|
||||
private void WhereAny<TRecord, TKey>(Expression<Func<TRecord, IEnumerable<TKey>>> selector, Expression<Func<TKey, bool>> predicate) where TRecord : ContentPartRecord {
|
||||
//var address = BindPartQueryOver<TRecord>() QueryOver.Of<TRecord>().Where(selector);
|
||||
BindPartQueryOver<TRecord>().JoinQueryOver<TKey>(selector).Where(predicate);
|
||||
}
|
||||
// build a linq to nhibernate expression
|
||||
var options = new QueryOptions();
|
||||
var queryProvider = new NHibernateQueryProvider(BindSession(), options);
|
||||
var queryable = new Query<TRecord>(queryProvider, options).Where(predicate);
|
||||
|
||||
private void OrderBy<TRecord>(Expression<Func<TRecord, object>> keySelector) where TRecord : ContentPartRecord {
|
||||
BindPartQueryOver<TRecord>().OrderBy(keySelector).Asc();
|
||||
}
|
||||
// translate it into the nhibernate ICriteria implementation
|
||||
var criteria = (CriteriaImpl)queryProvider.TranslateExpression(queryable.Expression);
|
||||
|
||||
private void OrderByDescending<TRecord>(Expression<Func<TRecord, object>> keySelector) where TRecord : ContentPartRecord {
|
||||
BindPartQueryOver<TRecord>().OrderBy(keySelector).Desc();
|
||||
// attach the criterion from the predicate to this query's criteria for the record
|
||||
var recordCriteria = BindPartCriteria<TRecord>();
|
||||
foreach (var expressionEntry in criteria.IterateExpressionEntries()) {
|
||||
recordCriteria.Add(expressionEntry.Criterion);
|
||||
}
|
||||
}
|
||||
|
||||
private void OrderBy<TRecord, TKey>(Expression<Func<TRecord, TKey>> keySelector) where TRecord : ContentPartRecord {
|
||||
BindPartQueryOver<TRecord>().OrderBy(AddBox(keySelector)).Asc();
|
||||
// build a linq to nhibernate expression
|
||||
var options = new QueryOptions();
|
||||
var queryProvider = new NHibernateQueryProvider(BindSession(), options);
|
||||
var queryable = new Query<TRecord>(queryProvider, options).OrderBy(keySelector);
|
||||
|
||||
// translate it into the nhibernate ordering
|
||||
var criteria = (CriteriaImpl)queryProvider.TranslateExpression(queryable.Expression);
|
||||
|
||||
// attaching orderings to the query's criteria
|
||||
var recordCriteria = BindPartCriteria<TRecord>();
|
||||
foreach (var ordering in criteria.IterateOrderings()) {
|
||||
recordCriteria.AddOrder(ordering.Order);
|
||||
}
|
||||
}
|
||||
|
||||
private void OrderByDescending<TRecord, TKey>(Expression<Func<TRecord, TKey>> keySelector) where TRecord : ContentPartRecord {
|
||||
BindPartQueryOver<TRecord>().OrderBy(AddBox(keySelector)).Desc();
|
||||
}
|
||||
// build a linq to nhibernate expression
|
||||
var options = new QueryOptions();
|
||||
var queryProvider = new NHibernateQueryProvider(BindSession(), options);
|
||||
var queryable = new Query<TRecord>(queryProvider, options).OrderByDescending(keySelector);
|
||||
|
||||
private static Expression<Func<TInput, object>> AddBox<TInput, TOutput>
|
||||
(Expression<Func<TInput, TOutput>> expression) {
|
||||
// Add the boxing operation, but get a weakly typed expression
|
||||
Expression converted = Expression.Convert
|
||||
(expression.Body, typeof(object));
|
||||
// Use Expression.Lambda to get back to strong typing
|
||||
return Expression.Lambda<Func<TInput, object>>
|
||||
(converted, expression.Parameters);
|
||||
// translate it into the nhibernate ICriteria implementation
|
||||
var criteria = (CriteriaImpl)queryProvider.TranslateExpression(queryable.Expression);
|
||||
|
||||
// attaching orderings to the query's criteria
|
||||
var recordCriteria = BindPartCriteria<TRecord>();
|
||||
foreach (var ordering in criteria.IterateOrderings()) {
|
||||
recordCriteria.AddOrder(ordering.Order);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<ContentItem> Slice(int skip, int count) {
|
||||
var queryOver = BindItemVersionQueryOver();
|
||||
var criteria = BindItemVersionCriteria();
|
||||
|
||||
criteria.ApplyVersionOptionsRestrictions(_versionOptions);
|
||||
|
||||
queryOver.ApplyVersionOptionsRestrictions(_versionOptions);
|
||||
criteria.SetFetchMode("ContentItemRecord", FetchMode.Eager);
|
||||
criteria.SetFetchMode("ContentItemRecord.ContentType", FetchMode.Eager);
|
||||
|
||||
// TODO: put 'removed false' filter in place
|
||||
if (skip != 0) {
|
||||
queryOver.Skip(skip);
|
||||
criteria = criteria.SetFirstResult(skip);
|
||||
}
|
||||
|
||||
if (count != 0) {
|
||||
queryOver.Take(count);
|
||||
criteria = criteria.SetMaxResults(count);
|
||||
}
|
||||
|
||||
var result = queryOver
|
||||
.List<ContentItemVersionRecord>()
|
||||
.Select(x => ContentManager.Get(x.Id, VersionOptions.VersionRecord(x.Id)))
|
||||
.ToList();
|
||||
|
||||
return new ReadOnlyCollection<ContentItem>(result);
|
||||
return criteria
|
||||
.List<ContentItemVersionRecord>()
|
||||
.Select(x => ContentManager.Get(x.Id, VersionOptions.VersionRecord(x.Id)))
|
||||
.ToReadOnlyCollection();
|
||||
}
|
||||
|
||||
int Count() {
|
||||
var queryOver = BindItemVersionQueryOver();
|
||||
var criteria = (ICriteria)BindItemVersionCriteria().Clone();
|
||||
criteria.ClearOrders();
|
||||
|
||||
// clone the query so that it doesn't affect the current one
|
||||
var countQuery = queryOver.Clone();
|
||||
countQuery.ClearOrders();
|
||||
criteria.ApplyVersionOptionsRestrictions(_versionOptions);
|
||||
|
||||
countQuery.ApplyVersionOptionsRestrictions(_versionOptions);
|
||||
|
||||
return countQuery.Select(Projections.RowCount()).FutureValue<int>().Value;
|
||||
return criteria.SetProjection(Projections.RowCount()).UniqueResult<Int32>();
|
||||
}
|
||||
|
||||
IContentQuery<TPart> IContentQuery.ForPart<TPart>() {
|
||||
@@ -226,23 +210,13 @@ namespace Orchard.ContentManagement {
|
||||
|
||||
IContentQuery<T, TRecord> IContentQuery<T>.OrderBy<TRecord>(Expression<Func<TRecord, object>> keySelector) {
|
||||
_query.OrderBy(keySelector);
|
||||
return new ContentQuery<T, TRecord>(_query);
|
||||
return new ContentQuery<T, TRecord>(_query);
|
||||
}
|
||||
|
||||
IContentQuery<T, TRecord> IContentQuery<T>.OrderByDescending<TRecord>(Expression<Func<TRecord, object>> keySelector) {
|
||||
_query.OrderByDescending(keySelector);
|
||||
return new ContentQuery<T, TRecord>(_query);
|
||||
}
|
||||
|
||||
IContentQuery<T, TRecord> IContentQuery<T>.OrderBy<TRecord, TKey>(Expression<Func<TRecord, TKey>> keySelector) {
|
||||
_query.OrderBy(AddBox(keySelector));
|
||||
return new ContentQuery<T, TRecord>(_query);
|
||||
}
|
||||
|
||||
IContentQuery<T, TRecord> IContentQuery<T>.OrderByDescending<TRecord, TKey>(Expression<Func<TRecord, TKey>> keySelector) {
|
||||
_query.OrderByDescending(AddBox(keySelector));
|
||||
return new ContentQuery<T, TRecord>(_query);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -263,11 +237,6 @@ namespace Orchard.ContentManagement {
|
||||
return this;
|
||||
}
|
||||
|
||||
IContentQuery<T, TR> IContentQuery<T, TR>.WhereAny<TKey>(Expression<Func<TR, IEnumerable<TKey>>> selector, Expression<Func<TKey, bool>> predicate) {
|
||||
_query.WhereAny(selector, predicate);
|
||||
return this;
|
||||
}
|
||||
|
||||
IContentQuery<T, TR> IContentQuery<T, TR>.OrderBy<TKey>(Expression<Func<TR, TKey>> keySelector) {
|
||||
_query.OrderBy(keySelector);
|
||||
return this;
|
||||
@@ -278,23 +247,14 @@ namespace Orchard.ContentManagement {
|
||||
return this;
|
||||
}
|
||||
|
||||
IContentQuery<T, TR> IContentQuery<T, TR>.OrderBy(Expression<Func<TR, object>> keySelector) {
|
||||
_query.OrderBy(keySelector);
|
||||
return this;
|
||||
}
|
||||
|
||||
IContentQuery<T, TR> IContentQuery<T, TR>.OrderByDescending(Expression<Func<TR, object>> keySelector) {
|
||||
_query.OrderByDescending(keySelector);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IContentQuery<T, TR> WithQueryHints(QueryHints hints) {
|
||||
if (hints == QueryHints.Empty) {
|
||||
return this;
|
||||
}
|
||||
|
||||
var contentItemVersionCriteria = _query.BindItemVersionQueryOver();
|
||||
var contentItemCriteria = _query.BindItemQueryOver();
|
||||
var contentItemVersionCriteria = _query.BindItemVersionCriteria();
|
||||
var contentItemCriteria = _query.BindItemCriteria();
|
||||
|
||||
var contentItemMetadata = _query._session.SessionFactory.GetClassMetadata(typeof(ContentItemRecord));
|
||||
var contentItemVersionMetadata = _query._session.SessionFactory.GetClassMetadata(typeof(ContentItemVersionRecord));
|
||||
@@ -307,18 +267,18 @@ namespace Orchard.ContentManagement {
|
||||
|
||||
// locate hints that match properties in the ContentItemVersionRecord
|
||||
foreach (var hit in contentItemVersionMetadata.PropertyNames.Where(hintDictionary.ContainsKey).SelectMany(key => hintDictionary[key])) {
|
||||
contentItemVersionCriteria.UnderlyingCriteria.SetFetchMode(hit.Hint, FetchMode.Eager);
|
||||
hit.Segments.Take(hit.Segments.Count() - 1).Aggregate(contentItemVersionCriteria.UnderlyingCriteria, ExtendCriteria);
|
||||
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.UnderlyingCriteria.SetFetchMode("ContentItemRecord." + hit.Hint, FetchMode.Eager);
|
||||
hit.Segments.Take(hit.Segments.Count() - 1).Aggregate(contentItemCriteria.UnderlyingCriteria, ExtendCriteria);
|
||||
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.TransformUsing(new DistinctRootEntityResultTransformer());
|
||||
contentItemVersionCriteria.SetResultTransformer(new DistinctRootEntityResultTransformer());
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -344,18 +304,18 @@ namespace Orchard.ContentManagement {
|
||||
}
|
||||
|
||||
internal static class CriteriaExtensions {
|
||||
internal static void ApplyVersionOptionsRestrictions<T>(this IQueryOver<T, T> criteria, VersionOptions versionOptions) {
|
||||
internal static void ApplyVersionOptionsRestrictions(this ICriteria criteria, VersionOptions versionOptions) {
|
||||
if (versionOptions == null) {
|
||||
criteria.Where(Restrictions.Eq("Published", true));
|
||||
criteria.Add(Restrictions.Eq("Published", true));
|
||||
}
|
||||
else if (versionOptions.IsPublished) {
|
||||
criteria.Where(Restrictions.Eq("Published", true));
|
||||
criteria.Add(Restrictions.Eq("Published", true));
|
||||
}
|
||||
else if (versionOptions.IsLatest) {
|
||||
criteria.Where(Restrictions.Eq("Latest", true));
|
||||
criteria.Add(Restrictions.Eq("Latest", true));
|
||||
}
|
||||
else if (versionOptions.IsDraft) {
|
||||
criteria.Where(Restrictions.And(
|
||||
criteria.Add(Restrictions.And(
|
||||
Restrictions.Eq("Latest", true),
|
||||
Restrictions.Eq("Published", false)));
|
||||
}
|
||||
|
@@ -23,19 +23,12 @@ namespace Orchard.ContentManagement {
|
||||
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> OrderByDescending<TRecord>(Expression<Func<TRecord, object>> keySelector) where TRecord : ContentPartRecord;
|
||||
|
||||
IContentQuery<TPart, TRecord> OrderBy<TRecord, TKey>(Expression<Func<TRecord, TKey>> keySelector) where TRecord : ContentPartRecord;
|
||||
IContentQuery<TPart, TRecord> OrderByDescending<TRecord, TKey>(Expression<Func<TRecord, TKey>> keySelector) where TRecord : ContentPartRecord;
|
||||
}
|
||||
|
||||
public interface IContentQuery<TPart, TRecord> : IContentQuery<TPart> where TPart : IContent where TRecord : ContentPartRecord {
|
||||
new IContentQuery<TPart, TRecord> ForVersion(VersionOptions options);
|
||||
|
||||
IContentQuery<TPart, TRecord> Where(Expression<Func<TRecord, bool>> predicate);
|
||||
IContentQuery<TPart, TRecord> WhereAny<TKey>(Expression<Func<TRecord, IEnumerable<TKey>>> selector, Expression<Func<TKey, bool>> predicate);
|
||||
IContentQuery<TPart, TRecord> OrderBy(Expression<Func<TRecord, object>> keySelector);
|
||||
IContentQuery<TPart, TRecord> OrderByDescending(Expression<Func<TRecord, object>> keySelector);
|
||||
|
||||
IContentQuery<TPart, TRecord> OrderBy<TKey>(Expression<Func<TRecord, TKey>> keySelector);
|
||||
IContentQuery<TPart, TRecord> OrderByDescending<TKey>(Expression<Func<TRecord, TKey>> keySelector);
|
||||
|
||||
|
@@ -1,41 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using NHibernate.Criterion;
|
||||
using NHibernate.Impl;
|
||||
using Orchard.ContentManagement.Records;
|
||||
|
||||
namespace Orchard.ContentManagement {
|
||||
public static class RestrictionExtensions {
|
||||
public static void RegisterExtensions() {
|
||||
ExpressionProcessor.RegisterCustomMethodCall(() => "".StartsWith(""), RestrictionExtensions.ProcessStartsWith);
|
||||
ExpressionProcessor.RegisterCustomMethodCall(() => "".EndsWith(""), RestrictionExtensions.ProcessEndsWith);
|
||||
ExpressionProcessor.RegisterCustomMethodCall(() => "".Contains(""), RestrictionExtensions.ProcessContains);
|
||||
}
|
||||
|
||||
public static ICriterion ProcessStartsWith(MethodCallExpression methodCallExpression) {
|
||||
ExpressionProcessor.ProjectionInfo projection = ExpressionProcessor.FindMemberProjection(methodCallExpression.Object);
|
||||
string value = (string)ExpressionProcessor.FindValue(methodCallExpression.Arguments[0]);
|
||||
MatchMode matchMode = MatchMode.Start;
|
||||
return projection.Create<ICriterion>(s => Restrictions.InsensitiveLike(s, value, matchMode), p => Restrictions.InsensitiveLike(p, value, matchMode));
|
||||
}
|
||||
|
||||
|
||||
public static ICriterion ProcessEndsWith(MethodCallExpression methodCallExpression) {
|
||||
ExpressionProcessor.ProjectionInfo projection = ExpressionProcessor.FindMemberProjection(methodCallExpression.Object);
|
||||
string value = (string)ExpressionProcessor.FindValue(methodCallExpression.Arguments[0]);
|
||||
MatchMode matchMode = MatchMode.End;
|
||||
return projection.Create<ICriterion>(s => Restrictions.InsensitiveLike(s, value, matchMode), p => Restrictions.InsensitiveLike(p, value, matchMode));
|
||||
}
|
||||
|
||||
|
||||
public static ICriterion ProcessContains(MethodCallExpression methodCallExpression) {
|
||||
ExpressionProcessor.ProjectionInfo projection = ExpressionProcessor.FindMemberProjection(methodCallExpression.Object);
|
||||
string value = (string)ExpressionProcessor.FindValue(methodCallExpression.Arguments[0]);
|
||||
MatchMode matchMode = MatchMode.Anywhere;
|
||||
return projection.Create<ICriterion>(s => Restrictions.InsensitiveLike(s, value, matchMode), p => Restrictions.InsensitiveLike(p, value, matchMode));
|
||||
}
|
||||
}
|
||||
}
|
@@ -96,6 +96,9 @@
|
||||
<Reference Include="NHibernate.Caches.SysCache2">
|
||||
<HintPath>..\..\lib\nhibernate\NHibernate.Caches.SysCache2.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NHibernate.Linq">
|
||||
<HintPath>..\..\lib\nhibernate.linq\NHibernate.Linq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
@@ -171,7 +174,6 @@
|
||||
<Compile Include="ContentManagement\ImportContentSession.cs" />
|
||||
<Compile Include="ContentManagement\MetaData\Services\ISettingsFormatter.cs" />
|
||||
<Compile Include="ContentManagement\QueryHints.cs" />
|
||||
<Compile Include="ContentManagement\RestrictionExtensions.cs" />
|
||||
<Compile Include="ContentManagement\Utilities\ComputedField.cs" />
|
||||
<Compile Include="Data\Conventions\AggregateAttribute.cs" />
|
||||
<Compile Include="Data\Conventions\CacheConvention.cs" />
|
||||
|
Reference in New Issue
Block a user