Skip to content

Instantly share code, notes, and snippets.

@ldhertert
Created June 29, 2011 19:16
Show Gist options
  • Save ldhertert/1054658 to your computer and use it in GitHub Desktop.
Save ldhertert/1054658 to your computer and use it in GitHub Desktop.
Linq implementation of ContentQuery
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using NHibernate;
using NHibernate.Criterion;
using NHibernate.Impl;
using NHibernate.Linq;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Records;
using Orchard.Data;
using Orchard.Environment.Extensions;
using Orchard.Utility.Extensions;
using Orchard;
namespace SchoolPointe.ContentQuery.Services
{
public class TestContentQuery : IContentQuery
{
private readonly ISessionLocator _sessionLocator;
public TestContentQuery(IContentManager contentManager, ISessionLocator sessionLocator)
{
_sessionLocator = sessionLocator;
ContentManager = contentManager;
}
public IContentManager ContentManager { get; private set; }
IContentQuery<TPart> IContentQuery.ForPart<TPart>() {
return new ContentQuery<TPart>(ContentManager, _sessionLocator);
}
protected class ContentQuery<T> : IContentQuery<T> where T : IContent
{
protected readonly ISessionLocator _sessionLocator;
protected ISession _session;
private IQueryable<ContentItemVersionRecord> _queryable;
public ContentQuery(IContentManager contentManager, ISessionLocator sessionLocator)
{
ContentManager = contentManager;
_sessionLocator = sessionLocator;
}
public IContentManager ContentManager { get; private set; }
protected IQueryable<ContentItemVersionRecord> Queryable
{
get { return _queryable ?? (_queryable = BindSession().Linq<ContentItemVersionRecord>()); }
set { _queryable = value; }
}
protected ISession BindSession()
{
if (_session == null)
_session = _sessionLocator.For(typeof(ContentItemVersionRecord));
return _session;
}
IContentQuery<TPart> IContentQuery.ForPart<TPart>()
{
return new ContentQuery<TPart>(ContentManager, _sessionLocator);
}
IContentQuery<T> IContentQuery<T>.ForType(params string[] contentTypes)
{
Queryable = Queryable.Where(r => contentTypes.Contains(r.ContentItemRecord.ContentType.Name));
return this;
}
IContentQuery<T> IContentQuery<T>.ForVersion(VersionOptions options)
{
if (options == null)
Queryable = Queryable.Where(r => r.Published);
else if (options.IsPublished)
Queryable = Queryable.Where(r => r.Published);
else if (options.IsLatest)
Queryable = Queryable.Where(r => r.Latest);
else if (options.IsDraft)
Queryable = Queryable.Where(r => r.Latest && !r.Published);
else if (options.IsAllVersions)
{
// no-op... all versions will be returned by default
}
else
throw new ApplicationException("Invalid VersionOptions for content query");
return this;
}
IEnumerable<T> IContentQuery<T>.List()
{
return Queryable
.AsEnumerable()
.Select(x => ContentManager.Get(x.Id, VersionOptions.VersionRecord(x.Id)))
.ToReadOnlyCollection()
.AsPart<T>();
}
IEnumerable<T> IContentQuery<T>.Slice(int skip, int count)
{
return Queryable
.Skip(skip)
.Take(count)
.AsEnumerable()
.Select(x => ContentManager.Get(x.Id, VersionOptions.VersionRecord(x.Id)))
.ToReadOnlyCollection()
.AsPart<T>();
}
int IContentQuery<T>.Count()
{
return Queryable.Count();
}
IContentQuery<T, TRecord> IContentQuery<T>.Join<TRecord>()
{
return new ContentQuery<T, TRecord>(ContentManager, _sessionLocator, Queryable);
}
IContentQuery<T, TRecord> IContentQuery<T>.Where<TRecord>(Expression<Func<TRecord, bool>> predicate)
{
var newQuery = ((IContentQuery<T, TRecord>)new ContentQuery<T, TRecord>(ContentManager, _sessionLocator, Queryable));
newQuery = newQuery.Where(predicate);
return newQuery;
}
IContentQuery<T, TRecord> IContentQuery<T>.OrderBy<TRecord, TKey>(Expression<Func<TRecord, TKey>> keySelector)
{
var newQuery = ((IContentQuery<T, TRecord>)new ContentQuery<T, TRecord>(ContentManager, _sessionLocator, Queryable));
newQuery = newQuery.OrderBy(keySelector);
return newQuery;
}
IContentQuery<T, TRecord> IContentQuery<T>.OrderByDescending<TRecord, TKey>(Expression<Func<TRecord, TKey>> keySelector)
{
var newQuery = ((IContentQuery<T, TRecord>)new ContentQuery<T, TRecord>(ContentManager, _sessionLocator, Queryable));
newQuery = newQuery.OrderByDescending(keySelector);
return newQuery;
}
}
class ContentQuery<T, TR> : TestContentQuery.ContentQuery<T>, IContentQuery<T, TR>
where T : IContent
where TR : ContentPartRecord
{
private IQueryable<TR> _joinedQuery;
public ContentQuery(IContentManager contentManager, ISessionLocator sessionLocator, IQueryable<ContentItemVersionRecord> queryable)
: base(contentManager, sessionLocator)
{
Queryable = queryable;
_joinedQuery = BindSession().Linq<TR>();
}
IContentQuery<T, TR> IContentQuery<T, TR>.ForVersion(VersionOptions options)
{
if (options == null)
Queryable = Queryable.Where(r => r.Published);
else if (options.IsPublished)
Queryable = Queryable.Where(r => r.Published);
else if (options.IsLatest)
Queryable = Queryable.Where(r => r.Latest);
else if (options.IsDraft)
Queryable = Queryable.Where(r => r.Latest && !r.Published);
else if (options.IsAllVersions)
{
// no-op... all versions will be returned by default
}
else
throw new ApplicationException("Invalid VersionOptions for content query");
return this;
}
IEnumerable<T> IContentQuery<T>.List()
{
Queryable = Queryable.Join(
_joinedQuery,
rec => rec.Id,
trec => trec.Id,
(rec, trec) => rec
);
return Queryable
.AsEnumerable()
.Select(x => ContentManager.Get(x.Id, VersionOptions.VersionRecord(x.Id)))
.ToReadOnlyCollection()
.AsPart<T>();
}
IEnumerable<T> IContentQuery<T>.Slice(int skip, int count)
{
Queryable = Queryable.Join(
_joinedQuery,
rec => rec.Id,
trec => trec.Id,
(rec, trec) => rec
);
return Queryable
.Skip(skip)
.Take(count)
.AsEnumerable()
.Select(x => ContentManager.Get(x.Id, VersionOptions.VersionRecord(x.Id)))
.ToReadOnlyCollection()
.AsPart<T>();
}
int IContentQuery<T>.Count()
{
return Queryable.Join(
_joinedQuery,
rec => rec.Id,
trec => trec.Id,
(rec, trec) => rec
).Count();
}
IContentQuery<T, TRecord> IContentQuery<T>.Join<TRecord>()
{
Queryable = Queryable.Join(
_joinedQuery,
rec => rec.Id,
trec => trec.Id,
(rec, trec) => rec
);
return new ContentQuery<T, TRecord>(ContentManager, _sessionLocator, Queryable);
}
IContentQuery<T, TR> IContentQuery<T, TR>.Where(Expression<Func<TR, bool>> predicate)
{
_joinedQuery = _joinedQuery.Where(predicate);
return this;
}
IContentQuery<T, TR> IContentQuery<T, TR>.OrderBy<TKey>(Expression<Func<TR, TKey>> keySelector)
{
_joinedQuery = _joinedQuery.OrderBy(keySelector);
return this;
}
IContentQuery<T, TR> IContentQuery<T, TR>.OrderByDescending<TKey>(Expression<Func<TR, TKey>> keySelector)
{
_joinedQuery = _joinedQuery.OrderByDescending(keySelector);
return this;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment