mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-12-02 19:44:02 +08:00
Using Hql in dynamic queries
--HG-- branch : 1.x
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
ec573e5476f7e8a5a61593d6393e9985e9484fcc src/Orchard.Web/Modules/Orchard.Forms
|
||||
d3ffae8d849f6b10eb1c4421f7b18e1d05edc85e src/Orchard.Web/Modules/Orchard.Projections
|
||||
4e99d7e20caab07ddbdcf9c780525613bcf8a15b src/Orchard.Web/Modules/Orchard.Projections
|
||||
01b83c05050bb731d9f69256bbe8884d458ea1c9 src/Orchard.Web/Modules/Orchard.Rules
|
||||
65057c6a5cd71f7994ba9bcbeece50dbb737620e src/Orchard.Web/Modules/Orchard.TaskLease
|
||||
c2e3c396c1fc6c60b131bfc9f83564c6f8d18e58 src/Orchard.Web/Modules/Orchard.Tokens
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace Orchard.Tests.ContentManagement {
|
||||
public void SpecificTypeIsReturnedWhenSpecified() {
|
||||
AddSampleData();
|
||||
|
||||
var alphaBeta = _manager.Query().Where(x => x.WithRecord("ContentType").In("Name", new [] {"alpha", "beta"})).List();
|
||||
var alphaBeta = _manager.HqlQuery().ForType("alpha", "beta").List();
|
||||
|
||||
Assert.That(alphaBeta.Count(), Is.EqualTo(2));
|
||||
Assert.That(alphaBeta.Count(x => x.Has<AlphaPart>()), Is.EqualTo(1));
|
||||
@@ -101,7 +101,7 @@ namespace Orchard.Tests.ContentManagement {
|
||||
Assert.That(alphaBeta.Count(x => x.Has<GammaPart>()), Is.EqualTo(0));
|
||||
Assert.That(alphaBeta.Count(x => x.Has<DeltaPart>()), Is.EqualTo(0));
|
||||
|
||||
var gammaDelta = _manager.Query().Where(x => x.WithRecord("ContentType").In("Name", new[] { "gamma", "delta" })).List();
|
||||
var gammaDelta = _manager.HqlQuery().ForType("gamma", "delta").List();
|
||||
|
||||
Assert.That(gammaDelta.Count(), Is.EqualTo(2));
|
||||
Assert.That(gammaDelta.Count(x => x.Has<AlphaPart>()), Is.EqualTo(0));
|
||||
@@ -119,8 +119,11 @@ namespace Orchard.Tests.ContentManagement {
|
||||
_manager.Create<GammaPart>("gamma", init => { init.Record.Frap = "four"; });
|
||||
_session.Flush();
|
||||
|
||||
var twoOrFour = _manager.Query<GammaPart, GammaRecord>()
|
||||
.Where(x => x.WithRecord("GammaRecord").Or(a => a.Eq("Frap", "one"), b => b.Eq("Frap", "four")))
|
||||
var twoOrFour = _manager
|
||||
.HqlQuery()
|
||||
.Where(
|
||||
alias => alias.ContentPartRecord<GammaRecord>(),
|
||||
x => x.Or(a => a.Eq("Frap", "one"), b => b.Eq("Frap", "four")))
|
||||
.List();
|
||||
|
||||
Assert.That(twoOrFour.Count(), Is.EqualTo(2));
|
||||
@@ -133,8 +136,8 @@ namespace Orchard.Tests.ContentManagement {
|
||||
[Test]
|
||||
public void EmptyWherePredicateRequiresRecord() {
|
||||
AddSampleData();
|
||||
var gammas = _manager.Query().Where(x => x.WithRecord("GammaRecord")).List(); // simulates an inner join
|
||||
var deltas = _manager.Query().Where(x => x.WithRecord("DeltaRecord")).List();
|
||||
var gammas = _manager.HqlQuery().Join(alias => alias.ContentPartRecord<GammaRecord>()).List();
|
||||
var deltas = _manager.HqlQuery().Join(alias => alias.ContentPartRecord<DeltaRecord>()).List();
|
||||
|
||||
Assert.That(gammas.Count(), Is.EqualTo(1));
|
||||
Assert.That(deltas.Count(), Is.EqualTo(1));
|
||||
@@ -152,9 +155,10 @@ namespace Orchard.Tests.ContentManagement {
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
|
||||
var ascending = _manager.Query("gamma")
|
||||
.OrderBy(x => x.WithRecord("GammaRecord").Asc("Frap"))
|
||||
.List<GammaPart>().ToList();
|
||||
var ascending = _manager.HqlQuery<GammaPart>()
|
||||
.ForType("gamma")
|
||||
.OrderBy(alias => alias.ContentPartRecord<GammaRecord>(), x => x.Asc("Frap"))
|
||||
.List().ToList();
|
||||
|
||||
Assert.That(ascending.Count(), Is.EqualTo(5));
|
||||
Assert.That(ascending.First().Record.Frap, Is.EqualTo("four"));
|
||||
@@ -162,8 +166,9 @@ namespace Orchard.Tests.ContentManagement {
|
||||
|
||||
_session.Clear();
|
||||
|
||||
var descending = _manager.Query<GammaPart, GammaRecord>()
|
||||
.OrderBy(x => x.WithRecord("GammaRecord").Desc("Frap"))
|
||||
var descending = _manager.HqlQuery<GammaPart>()
|
||||
.ForType("gamma")
|
||||
.OrderBy(alias => alias.ContentPartRecord<GammaRecord>(), x => x.Desc("Frap"))
|
||||
.List().ToList();
|
||||
|
||||
Assert.That(descending.Count(), Is.EqualTo(5));
|
||||
@@ -180,12 +185,12 @@ namespace Orchard.Tests.ContentManagement {
|
||||
_manager.Create<GammaPart>("gamma", init => { init.Record.Frap = "four"; });
|
||||
_session.Flush();
|
||||
|
||||
var reverseById = _manager.Query()
|
||||
.OrderBy(x => x.WithRecord("GammaRecord").Desc("Id"))
|
||||
var reverseById = _manager.HqlQuery()
|
||||
.OrderBy(alias => alias.ContentPartRecord<GammaRecord>(), x => x.Desc("Id"))
|
||||
.List();
|
||||
|
||||
var subset = _manager.Query()
|
||||
.OrderBy(x => x.WithRecord("GammaRecord").Desc("Id"))
|
||||
var subset = _manager.HqlQuery()
|
||||
.OrderBy(alias => alias.ContentPartRecord<GammaRecord>(), x => x.Desc("Id"))
|
||||
.Slice(2, 3);
|
||||
|
||||
Assert.That(subset.Count(), Is.EqualTo(3));
|
||||
@@ -217,10 +222,11 @@ namespace Orchard.Tests.ContentManagement {
|
||||
_session.Flush();
|
||||
_session.Clear();
|
||||
|
||||
var results = _manager.Query("gamma")
|
||||
.Where(x => x.WithVersionRecord("EpsilonRecord").Or(a => a.Eq("Quad", "2"), b => b.Eq("Quad", "3")))
|
||||
.OrderBy(x => x.WithVersionRecord("EpsilonRecord").Desc("Quad"))
|
||||
.List<EpsilonPart>();
|
||||
var results = _manager.HqlQuery<EpsilonPart>()
|
||||
.Where(alias => alias.ContentPartRecord<EpsilonRecord>(), x => x.Or(a => a.Eq("Quad", "2"), b => b.Eq("Quad", "3")))
|
||||
.OrderBy(alias => alias.ContentPartRecord<EpsilonRecord>(), x => x.Desc("Quad"))
|
||||
.ForType("gamma")
|
||||
.List();
|
||||
|
||||
Assert.That(results.Count(), Is.EqualTo(2));
|
||||
Assert.That(results.First().Record, Has.Property("Quad").EqualTo("3"));
|
||||
|
||||
@@ -74,12 +74,18 @@ namespace Orchard.ContentManagement {
|
||||
where TPart : ContentPart {
|
||||
return manager.Query().ForPart<TPart>();
|
||||
}
|
||||
|
||||
public static IContentQuery<TPart, TRecord> Query<TPart, TRecord>(this IContentManager manager)
|
||||
where TPart : ContentPart<TRecord>
|
||||
where TRecord : ContentPartRecord {
|
||||
return manager.Query().ForPart<TPart>().Join<TRecord>();
|
||||
}
|
||||
|
||||
public static IHqlQuery<TPart> HqlQuery<TPart>(this IContentManager manager)
|
||||
where TPart : ContentPart {
|
||||
return manager.HqlQuery().ForPart<TPart>();
|
||||
}
|
||||
|
||||
/* Query(VersionOptions options) */
|
||||
|
||||
public static IContentQuery<ContentItem> Query(this IContentManager manager, VersionOptions options) {
|
||||
|
||||
@@ -487,6 +487,10 @@ namespace Orchard.ContentManagement {
|
||||
return query.ForPart<ContentItem>();
|
||||
}
|
||||
|
||||
public IHqlQuery HqlQuery() {
|
||||
return new DefaultHqlQuery(this, _sessionLocator.Value.For(typeof(ContentItemVersionRecord)));
|
||||
}
|
||||
|
||||
// Insert or Update imported data into the content manager.
|
||||
// Call content item handlers.
|
||||
public void Import(XElement element, ImportContentSession importContentSession) {
|
||||
|
||||
390
src/Orchard/ContentManagement/DefaultHqlQuery.cs
Normal file
390
src/Orchard/ContentManagement/DefaultHqlQuery.cs
Normal file
@@ -0,0 +1,390 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NHibernate;
|
||||
using Orchard.ContentManagement.Records;
|
||||
using Orchard.Utility.Extensions;
|
||||
|
||||
namespace Orchard.ContentManagement {
|
||||
|
||||
public class DefaultHqlQuery : IHqlQuery {
|
||||
private readonly ISession _session;
|
||||
private VersionOptions _versionOptions;
|
||||
|
||||
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>>>();
|
||||
|
||||
public IContentManager ContentManager { get; private set; }
|
||||
|
||||
public DefaultHqlQuery(IContentManager contentManager, ISession session) {
|
||||
_session = session;
|
||||
ContentManager = contentManager;
|
||||
}
|
||||
|
||||
internal string PathToAlias(string path) {
|
||||
if (String.IsNullOrWhiteSpace(path)) {
|
||||
throw new ArgumentException("Path can't be empty");
|
||||
}
|
||||
|
||||
return Char.ToLower(path[0], CultureInfo.InvariantCulture) + path.Substring(1);
|
||||
}
|
||||
|
||||
internal Join BindNamedAlias(string alias) {
|
||||
var tuple = _joins.FirstOrDefault(x => x.Item2.Name == alias);
|
||||
return tuple == null ? null : tuple.Item2;
|
||||
}
|
||||
|
||||
internal IAlias BindCriteriaByPath(IAlias alias, string path) {
|
||||
return BindCriteriaByAlias(alias, path, PathToAlias(path));
|
||||
}
|
||||
|
||||
internal IAlias BindCriteriaByAlias(IAlias alias, string path, string aliasName) {
|
||||
// is this Join already existing (based on aliasName)
|
||||
|
||||
Join join = BindNamedAlias(aliasName);
|
||||
|
||||
if (join == null) {
|
||||
join = new Join(path, aliasName);
|
||||
_joins.Add(new Tuple<IAlias, Join>(alias, join));
|
||||
}
|
||||
|
||||
return join;
|
||||
}
|
||||
|
||||
internal IAlias BindTypeCriteria() {
|
||||
// ([ContentItemVersionRecord] >join> [ContentItemRecord]) >join> [ContentType]
|
||||
return BindCriteriaByAlias(BindItemCriteria(), "ContentType", "ct");
|
||||
}
|
||||
|
||||
internal IAlias BindItemCriteria() {
|
||||
// [ContentItemVersionRecord] >join> [ContentItemRecord]
|
||||
return BindCriteriaByAlias(BindItemVersionCriteria(), typeof(ContentItemRecord).Name, "ci");
|
||||
}
|
||||
|
||||
internal IAlias BindItemVersionCriteria() {
|
||||
return _from ?? (_from = new Join(typeof(ContentItemVersionRecord).FullName, "civ", ""));
|
||||
}
|
||||
|
||||
internal IAlias BindPartCriteria<TRecord>() where TRecord : ContentPartRecord {
|
||||
return BindPartCriteria(typeof(TRecord));
|
||||
}
|
||||
|
||||
internal IAlias BindPartCriteria(Type contentPartRecordType) {
|
||||
if (!contentPartRecordType.IsSubclassOf(typeof(ContentPartRecord))) {
|
||||
throw new ArgumentException("The type must inherit from ContentPartRecord", "contentPartRecordType");
|
||||
}
|
||||
|
||||
if (contentPartRecordType.IsSubclassOf(typeof(ContentPartVersionRecord))) {
|
||||
return BindCriteriaByPath(BindItemVersionCriteria(), contentPartRecordType.Name);
|
||||
}
|
||||
return BindCriteriaByPath(BindItemCriteria(), contentPartRecordType.Name);
|
||||
}
|
||||
|
||||
internal void Where(IAlias alias, Action<IHqlExpressionFactory> predicate) {
|
||||
_wheres.Add(new Tuple<IAlias, Action<IHqlExpressionFactory>>(alias, predicate));
|
||||
}
|
||||
|
||||
internal IAlias ApplyHqlVersionOptionsRestrictions(VersionOptions versionOptions) {
|
||||
var alias = BindItemVersionCriteria();
|
||||
|
||||
if (versionOptions == null) {
|
||||
Where(alias, x => x.Eq("Published", true));
|
||||
}
|
||||
else if (versionOptions.IsPublished) {
|
||||
Where(alias, x => x.Eq("Published", true));
|
||||
}
|
||||
else if (versionOptions.IsLatest) {
|
||||
Where(alias, x => x.Eq("Latest", true));
|
||||
}
|
||||
else if (versionOptions.IsDraft) {
|
||||
Where(alias, x => x.And(y => y.Eq("Latest", true), y => y.Eq("Published", false)));
|
||||
}
|
||||
else if (versionOptions.IsAllVersions) {
|
||||
// no-op... all versions will be returned by default
|
||||
}
|
||||
else {
|
||||
throw new ApplicationException("Invalid VersionOptions for content query");
|
||||
}
|
||||
|
||||
return alias;
|
||||
}
|
||||
|
||||
public IHqlQuery Join(Action<IAliasFactory> alias) {
|
||||
var aliasFactory = new DefaultAliasFactory(this);
|
||||
alias(aliasFactory);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IHqlQuery Where(Action<IAliasFactory> alias, Action<IHqlExpressionFactory> predicate) {
|
||||
var aliasFactory = new DefaultAliasFactory(this);
|
||||
alias(aliasFactory);
|
||||
Where(aliasFactory.Current, predicate);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IHqlQuery OrderBy(Action<IAliasFactory> alias, Action<IHqlSortFactory> order) {
|
||||
var aliasFactory = new DefaultAliasFactory(this);
|
||||
alias(aliasFactory);
|
||||
|
||||
_sortings.Add(new Tuple<IAlias, Action<IHqlSortFactory>>(aliasFactory.Current, order));
|
||||
return this;
|
||||
}
|
||||
|
||||
public IHqlQuery ForType(params string[] contentTypeNames) {
|
||||
if (contentTypeNames != null && contentTypeNames.Length != 0) {
|
||||
Where(BindTypeCriteria(), x => x.InG("Name", contentTypeNames));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public IHqlQuery ForVersion(VersionOptions options) {
|
||||
_versionOptions = options;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IHqlQuery<T> ForPart<T>() where T : IContent {
|
||||
return new DefaultHqlQuery<T>(this);
|
||||
}
|
||||
|
||||
public IEnumerable<ContentItem> List() {
|
||||
return Slice(0, 0);
|
||||
}
|
||||
|
||||
public IEnumerable<ContentItem> Slice(int skip, int count) {
|
||||
ApplyHqlVersionOptionsRestrictions(_versionOptions);
|
||||
var hql = ToHql(false);
|
||||
var query = _session.CreateQuery(hql);
|
||||
|
||||
if (skip != 0) {
|
||||
query.SetFirstResult(skip);
|
||||
}
|
||||
if (count != 0) {
|
||||
query.SetMaxResults(count);
|
||||
}
|
||||
|
||||
return query.List<ContentItemVersionRecord>()
|
||||
.Select(x => ContentManager.Get(x.Id, VersionOptions.VersionRecord(x.Id)))
|
||||
.ToReadOnlyCollection();
|
||||
}
|
||||
|
||||
public int Count() {
|
||||
ApplyHqlVersionOptionsRestrictions(_versionOptions);
|
||||
return _session.CreateQuery(ToHql(true)).UniqueResult<int>();
|
||||
}
|
||||
|
||||
public string ToHql(bool count) {
|
||||
var sb = new StringBuilder();
|
||||
|
||||
if (count) {
|
||||
sb.Append("select count(civ) ").AppendLine();
|
||||
}
|
||||
else {
|
||||
sb.Append("select civ ").AppendLine();
|
||||
}
|
||||
|
||||
sb.Append("from ").Append(_from.TableName).Append(" as ").Append(_from.Name).AppendLine();
|
||||
|
||||
foreach (var join in _joins) {
|
||||
sb.Append(join.Item2.Type).Append(" ").Append(join.Item1.Name + "." + join.Item2.TableName).Append(" as ").Append(join.Item2.Name).AppendLine();
|
||||
}
|
||||
|
||||
#region Where
|
||||
|
||||
bool first = true;
|
||||
foreach (var where in _wheres) {
|
||||
if (!first) {
|
||||
sb.Append("and ");
|
||||
}
|
||||
else {
|
||||
sb.Append("where ");
|
||||
first = false;
|
||||
}
|
||||
|
||||
var expressionFactory = new DefaultHqlExpressionFactory();
|
||||
where.Item2(expressionFactory);
|
||||
sb.Append(expressionFactory.Criterion.ToHql(where.Item1)).AppendLine();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Order by
|
||||
|
||||
bool firstSort = true;
|
||||
foreach (var sort in _sortings) {
|
||||
if (!firstSort) {
|
||||
sb.Append(", ");
|
||||
}
|
||||
else {
|
||||
sb.Append("order by ");
|
||||
firstSort = false;
|
||||
}
|
||||
|
||||
var sortFactory = new DefaultHqlSortFactory();
|
||||
sort.Item2(sortFactory);
|
||||
|
||||
sb.Append(sort.Item1.Name).Append(".").Append(sortFactory.PropertyName);
|
||||
if (!sortFactory.Ascending) {
|
||||
sb.Append(" desc");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class DefaultHqlQuery<TPart> : IHqlQuery<TPart> where TPart : IContent {
|
||||
private readonly DefaultHqlQuery _query;
|
||||
|
||||
public DefaultHqlQuery(DefaultHqlQuery query) {
|
||||
_query = query;
|
||||
}
|
||||
|
||||
public IContentManager ContentManager {
|
||||
get { return _query.ContentManager; }
|
||||
}
|
||||
|
||||
public IHqlQuery<TPart> ForType(params string[] contentTypes) {
|
||||
_query.ForType(contentTypes);
|
||||
return new DefaultHqlQuery<TPart>(_query);
|
||||
}
|
||||
|
||||
public IHqlQuery<TPart> ForVersion(VersionOptions options) {
|
||||
_query.ForVersion(options);
|
||||
return new DefaultHqlQuery<TPart>(_query);
|
||||
}
|
||||
|
||||
IEnumerable<TPart> IHqlQuery<TPart>.List() {
|
||||
return _query.List().AsPart<TPart>();
|
||||
}
|
||||
|
||||
IEnumerable<TPart> IHqlQuery<TPart>.Slice(int skip, int count) {
|
||||
return _query.Slice(skip, count).AsPart<TPart>();
|
||||
}
|
||||
|
||||
int IHqlQuery<TPart>.Count() {
|
||||
return _query.Count();
|
||||
}
|
||||
|
||||
public IHqlQuery<TPart> Join(Action<IAliasFactory> alias) {
|
||||
_query.Join(alias);
|
||||
return new DefaultHqlQuery<TPart>(_query);
|
||||
}
|
||||
|
||||
public IHqlQuery<TPart> Where(Action<IAliasFactory> alias, Action<IHqlExpressionFactory> predicate) {
|
||||
_query.Where(alias, predicate);
|
||||
return new DefaultHqlQuery<TPart>(_query);
|
||||
}
|
||||
|
||||
public IHqlQuery<TPart> OrderBy(Action<IAliasFactory> alias, Action<IHqlSortFactory> order) {
|
||||
_query.OrderBy(alias, order);
|
||||
return new DefaultHqlQuery<TPart>(_query);
|
||||
}
|
||||
}
|
||||
|
||||
public class Alias : IAlias {
|
||||
public Alias(string name) {
|
||||
if (String.IsNullOrEmpty(name)) {
|
||||
throw new ArgumentException("Alias can't be empty");
|
||||
}
|
||||
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public DefaultHqlQuery<IContent> Query { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
public interface IJoin : IAlias {
|
||||
string TableName { get; set; }
|
||||
string Type { get; set; }
|
||||
}
|
||||
|
||||
public class Sort {
|
||||
|
||||
public Sort(IAlias alias, string propertyName, bool ascending) {
|
||||
Alias = alias;
|
||||
PropertyName = propertyName;
|
||||
Ascending = ascending;
|
||||
}
|
||||
|
||||
public IAlias Alias { get; set; }
|
||||
public string PropertyName { get; set; }
|
||||
public bool Ascending { get; set; }
|
||||
}
|
||||
|
||||
public class Join : Alias, IJoin {
|
||||
|
||||
public Join(string tableName, string alias)
|
||||
: this(tableName, alias, "join") {}
|
||||
|
||||
public Join(string tableName, string alias, string type)
|
||||
: base(alias) {
|
||||
if (String.IsNullOrEmpty(tableName)) {
|
||||
throw new ArgumentException("Table Name can't be empty");
|
||||
}
|
||||
|
||||
TableName = tableName;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public string TableName { get; set; }
|
||||
public string Type { get; set; }
|
||||
}
|
||||
|
||||
public class DefaultHqlSortFactory : IHqlSortFactory
|
||||
{
|
||||
public bool Ascending { get; set; }
|
||||
public string PropertyName { get; set; }
|
||||
|
||||
public void Asc(string propertyName) {
|
||||
PropertyName = propertyName;
|
||||
Ascending = true;
|
||||
}
|
||||
|
||||
public void Desc(string propertyName) {
|
||||
PropertyName = propertyName;
|
||||
Ascending = false;
|
||||
}
|
||||
}
|
||||
|
||||
public class DefaultAliasFactory : IAliasFactory{
|
||||
private readonly DefaultHqlQuery _query;
|
||||
public IAlias Current { get; private set; }
|
||||
|
||||
public DefaultAliasFactory(DefaultHqlQuery query) {
|
||||
_query = query;
|
||||
Current = _query.BindItemCriteria();
|
||||
}
|
||||
|
||||
public IAliasFactory ContentPartRecord<TRecord>() where TRecord : ContentPartRecord {
|
||||
Current = _query.BindPartCriteria<TRecord>();
|
||||
return this;
|
||||
}
|
||||
|
||||
public IAliasFactory ContentPartRecord(Type contentPartRecord) {
|
||||
if(!contentPartRecord.IsSubclassOf(typeof(ContentPartRecord))) {
|
||||
throw new ArgumentException("Type must inherit from ContentPartRecord", "contentPartRecord");
|
||||
}
|
||||
|
||||
Current = _query.BindPartCriteria(contentPartRecord);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IAliasFactory Property(string propertyName, string alias) {
|
||||
Current = _query.BindCriteriaByAlias(Current, propertyName, alias);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IAliasFactory Named(string alias) {
|
||||
Current = _query.BindNamedAlias(alias);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ namespace Orchard.ContentManagement {
|
||||
|
||||
void Flush();
|
||||
IContentQuery<ContentItem> Query();
|
||||
IHqlQuery HqlQuery();
|
||||
|
||||
ContentItemMetadata GetItemMetadata(IContent contentItem);
|
||||
IEnumerable<GroupInfo> GetEditorGroupInfos(IContent contentItem);
|
||||
|
||||
248
src/Orchard/ContentManagement/IHqlCriterion.cs
Normal file
248
src/Orchard/ContentManagement/IHqlCriterion.cs
Normal file
@@ -0,0 +1,248 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Orchard.ContentManagement {
|
||||
public interface IHqlCriterion {
|
||||
|
||||
string ToHql(IAlias alias);
|
||||
}
|
||||
|
||||
public abstract class HqlCriterion : IHqlCriterion {
|
||||
public abstract string ToHql(IAlias alias);
|
||||
}
|
||||
|
||||
public class BinaryExpression : HqlCriterion {
|
||||
public BinaryExpression(string op, string propertyName, string value, Func<string, string> processPropertyName = null) {
|
||||
if(value == null) {
|
||||
throw new ArgumentNullException("value");
|
||||
}
|
||||
|
||||
Op = op;
|
||||
PropertyName = propertyName;
|
||||
Value = value;
|
||||
ProcessPropertyName = processPropertyName;
|
||||
}
|
||||
|
||||
public string Op { get; set; }
|
||||
public string PropertyName { get; set; }
|
||||
public string Value { get; set; }
|
||||
public Func<string, string> ProcessPropertyName { get; set; }
|
||||
|
||||
public override string ToHql(IAlias alias) {
|
||||
var processed = String.Concat(alias.Name, ".", PropertyName);
|
||||
if(ProcessPropertyName != null) {
|
||||
processed = ProcessPropertyName(processed);
|
||||
}
|
||||
return String.Concat(processed, " ", Op, " ", Value);
|
||||
}
|
||||
}
|
||||
|
||||
public class CompositeHqlCriterion : HqlCriterion {
|
||||
public string Op { get; set; }
|
||||
public IList<IHqlCriterion> Criterions { get; private set; }
|
||||
|
||||
public CompositeHqlCriterion(string op) {
|
||||
Op = op;
|
||||
Criterions = new List<IHqlCriterion>();
|
||||
}
|
||||
|
||||
public CompositeHqlCriterion Add(IHqlCriterion criterion) {
|
||||
Criterions.Add(criterion);
|
||||
return this;
|
||||
}
|
||||
|
||||
public override string ToHql(IAlias alias) {
|
||||
var sb = new StringBuilder();
|
||||
var first = true;
|
||||
foreach(var criterion in Criterions) {
|
||||
if(!first) {
|
||||
sb.Append(Op).Append(" ");
|
||||
}
|
||||
else {
|
||||
first = false;
|
||||
}
|
||||
|
||||
sb.Append(criterion.ToHql(alias)).Append(" ");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public static class HqlRestrictions {
|
||||
|
||||
public static IEnumerable<string> FormatValue(IEnumerable values, bool quoteStrings = true) {
|
||||
return from object value in values select FormatValue(value, quoteStrings);
|
||||
}
|
||||
|
||||
public static string FormatValue(object value, bool quoteStrings = true) {
|
||||
var typeCode = Type.GetTypeCode(value.GetType());
|
||||
switch (typeCode) {
|
||||
case TypeCode.String:
|
||||
if (quoteStrings) {
|
||||
return String.Concat("'", Convert.ToString(value, CultureInfo.InvariantCulture), "'");
|
||||
}
|
||||
|
||||
return Convert.ToString(value, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
return Convert.ToString(value, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public static IHqlCriterion AllEq(IDictionary propertyNameValues) {
|
||||
var conjuction = new CompositeHqlCriterion("and");
|
||||
|
||||
foreach(string propertyName in propertyNameValues.Keys) {
|
||||
conjuction.Add(Eq(propertyName, propertyNameValues[propertyName]));
|
||||
}
|
||||
|
||||
return conjuction;
|
||||
}
|
||||
|
||||
public static IHqlCriterion And(IHqlCriterion lhs, IHqlCriterion rhs) {
|
||||
return new CompositeHqlCriterion("and")
|
||||
.Add(lhs)
|
||||
.Add(rhs);
|
||||
}
|
||||
|
||||
public static IHqlCriterion Between(string propertyName, object lo, object hi) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static CompositeHqlCriterion Conjunction() {
|
||||
return new CompositeHqlCriterion("and");
|
||||
}
|
||||
|
||||
public static CompositeHqlCriterion Disjunction() {
|
||||
return new CompositeHqlCriterion("or");
|
||||
}
|
||||
|
||||
public static IHqlCriterion Eq(string propertyName, object value) {
|
||||
return new BinaryExpression("=", propertyName, FormatValue(value));
|
||||
}
|
||||
|
||||
public static IHqlCriterion EqProperty(string propertyName, string otherPropertyName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IHqlCriterion Ge(string propertyName, object value) {
|
||||
return new BinaryExpression(">=", propertyName, FormatValue(value));
|
||||
}
|
||||
|
||||
public static IHqlCriterion GeProperty(string propertyName, string otherPropertyName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IHqlCriterion Gt(string propertyName, object value) {
|
||||
return new BinaryExpression(">", propertyName, FormatValue(value));
|
||||
}
|
||||
|
||||
public static IHqlCriterion GtProperty(string propertyName, string otherPropertyName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IHqlCriterion IdEq(object value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IHqlCriterion In(string propertyName, ICollection values) {
|
||||
if (values.Count == 0) {
|
||||
throw new ArgumentException("Collection can't be empty", "values");
|
||||
}
|
||||
return new BinaryExpression("in", propertyName, "(" + String.Join(", ", FormatValue(values)) + ")");
|
||||
}
|
||||
|
||||
public static IHqlCriterion In(string propertyName, object[] values) {
|
||||
if (values.Length == 0) {
|
||||
throw new ArgumentException("Collection can't be empty", "values");
|
||||
}
|
||||
return new BinaryExpression("in", propertyName, "(" + String.Join(", ", FormatValue(values)) + ")");
|
||||
}
|
||||
|
||||
public static IHqlCriterion InG<T>(string propertyName, ICollection<T> values) {
|
||||
if (values.Count == 0) {
|
||||
throw new ArgumentException("Collection can't be empty", "values");
|
||||
}
|
||||
return new BinaryExpression("in", propertyName, "(" + String.Join(", ", FormatValue(values)) + ")");
|
||||
}
|
||||
|
||||
public static IHqlCriterion InsensitiveLike(string propertyName, string value, HqlMatchMode matchMode) {
|
||||
var expression = Like(propertyName, value, matchMode);
|
||||
expression.ProcessPropertyName = x => String.Concat("lower(", x, ")");
|
||||
|
||||
return expression;
|
||||
}
|
||||
|
||||
public static IHqlCriterion IsEmpty(string propertyName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IHqlCriterion IsNotEmpty(string propertyName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IHqlCriterion IsNotNull(string propertyName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IHqlCriterion IsNull(string propertyName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IHqlCriterion Le(string propertyName, object value) {
|
||||
return new BinaryExpression("<=", propertyName, FormatValue(value));
|
||||
}
|
||||
|
||||
public static IHqlCriterion LeProperty(string propertyName, string otherPropertyName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static BinaryExpression Like(string propertyName, string value, HqlMatchMode matchMode) {
|
||||
switch (matchMode) {
|
||||
case HqlMatchMode.Start:
|
||||
value = "'" + value + "%'";
|
||||
break;
|
||||
case HqlMatchMode.Exact:
|
||||
break;
|
||||
case HqlMatchMode.Anywhere:
|
||||
value = "'%" + value + "%'";
|
||||
break;
|
||||
case HqlMatchMode.End:
|
||||
value = "'%" + value + "'";
|
||||
break;
|
||||
}
|
||||
|
||||
return new BinaryExpression("like", propertyName, FormatValue((object)value, false));
|
||||
}
|
||||
|
||||
public static IHqlCriterion Lt(string propertyName, object value) {
|
||||
return new BinaryExpression("<", propertyName, FormatValue(value));
|
||||
}
|
||||
|
||||
public static IHqlCriterion LtProperty(string propertyName, string otherPropertyName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IHqlCriterion NaturalId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IHqlCriterion Not(IHqlCriterion expression) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IHqlCriterion NotEqProperty(string propertyName, string otherPropertyName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IHqlCriterion Or(IHqlCriterion lhs, IHqlCriterion rhs) {
|
||||
return new CompositeHqlCriterion("or")
|
||||
.Add(lhs)
|
||||
.Add(rhs);
|
||||
}
|
||||
}
|
||||
}
|
||||
185
src/Orchard/ContentManagement/IHqlExpression.cs
Normal file
185
src/Orchard/ContentManagement/IHqlExpression.cs
Normal file
@@ -0,0 +1,185 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Orchard.ContentManagement {
|
||||
|
||||
public interface IHqlExpressionFactory {
|
||||
|
||||
void Eq(string propertyName, object value);
|
||||
void Like(string propertyName, string value, HqlMatchMode matchMode);
|
||||
void InsensitiveLike(string propertyName, string value, HqlMatchMode matchMode);
|
||||
void Gt(string propertyName, object value);
|
||||
void Lt(string propertyName, object value);
|
||||
void Le(string propertyName, object value);
|
||||
void Ge(string propertyName, object value);
|
||||
void Between(string propertyName, object lo, object hi);
|
||||
void In(string propertyName, object[] values);
|
||||
void In(string propertyName, ICollection values);
|
||||
void InG<T>(string propertyName, ICollection<T> values);
|
||||
void IsNull(string propertyName);
|
||||
void EqProperty(string propertyName, string otherPropertyName);
|
||||
void NotEqProperty(string propertyName, string otherPropertyName);
|
||||
void GtProperty(string propertyName, string otherPropertyName);
|
||||
void GeProperty(string propertyName, string otherPropertyName);
|
||||
void LtProperty(string propertyName, string otherPropertyName);
|
||||
void LeProperty(string propertyName, string otherPropertyName);
|
||||
void IsNotNull(string propertyName);
|
||||
void IsNotEmpty(string propertyName);
|
||||
void IsEmpty(string propertyName);
|
||||
void And(Action<IHqlExpressionFactory> lhs, Action<IHqlExpressionFactory> rhs);
|
||||
void Or(Action<IHqlExpressionFactory> lhs, Action<IHqlExpressionFactory> rhs);
|
||||
void Not(Action<IHqlExpressionFactory> expression);
|
||||
void Conjunction(Action<IHqlExpressionFactory> expression, params Action<IHqlExpressionFactory>[] otherExpressions);
|
||||
void Disjunction(Action<IHqlExpressionFactory> expression, params Action<IHqlExpressionFactory>[] otherExpressions);
|
||||
void AllEq(IDictionary propertyNameValues);
|
||||
void NaturalId();
|
||||
}
|
||||
|
||||
public class DefaultHqlExpressionFactory : IHqlExpressionFactory {
|
||||
public IHqlCriterion Criterion { get; private set; }
|
||||
|
||||
public void Eq(string propertyName, object value) {
|
||||
Criterion = HqlRestrictions.Eq(propertyName, value);
|
||||
}
|
||||
|
||||
public void Like(string propertyName, string value, HqlMatchMode matchMode) {
|
||||
Criterion = HqlRestrictions.Like(propertyName, value, matchMode);
|
||||
}
|
||||
|
||||
public void InsensitiveLike(string propertyName, string value, HqlMatchMode matchMode) {
|
||||
Criterion = HqlRestrictions.InsensitiveLike(propertyName, value, matchMode);
|
||||
}
|
||||
|
||||
public void Gt(string propertyName, object value) {
|
||||
Criterion = HqlRestrictions.Gt(propertyName, value);
|
||||
}
|
||||
|
||||
public void Lt(string propertyName, object value) {
|
||||
Criterion = HqlRestrictions.Lt(propertyName, value);
|
||||
}
|
||||
|
||||
public void Le(string propertyName, object value) {
|
||||
Criterion = HqlRestrictions.Le(propertyName, value);
|
||||
}
|
||||
|
||||
public void Ge(string propertyName, object value) {
|
||||
Criterion = HqlRestrictions.Ge(propertyName, value);
|
||||
}
|
||||
|
||||
public void Between(string propertyName, object lo, object hi) {
|
||||
Criterion = HqlRestrictions.Between(propertyName, lo, hi);
|
||||
}
|
||||
|
||||
public void In(string propertyName, object[] values) {
|
||||
Criterion = HqlRestrictions.In(propertyName, values);
|
||||
}
|
||||
|
||||
public void In(string propertyName, ICollection values) {
|
||||
Criterion = HqlRestrictions.In(propertyName, values);
|
||||
}
|
||||
|
||||
public void InG<T>(string propertyName, ICollection<T> values) {
|
||||
Criterion = HqlRestrictions.InG(propertyName, values);
|
||||
}
|
||||
|
||||
public void IsNull(string propertyName) {
|
||||
Criterion = HqlRestrictions.IsNull(propertyName);
|
||||
}
|
||||
|
||||
public void EqProperty(string propertyName, string otherPropertyName) {
|
||||
Criterion = HqlRestrictions.EqProperty(propertyName, otherPropertyName);
|
||||
}
|
||||
|
||||
public void NotEqProperty(string propertyName, string otherPropertyName) {
|
||||
Criterion = HqlRestrictions.NotEqProperty(propertyName, otherPropertyName);
|
||||
}
|
||||
|
||||
public void GtProperty(string propertyName, string otherPropertyName) {
|
||||
Criterion = HqlRestrictions.GtProperty(propertyName, otherPropertyName);
|
||||
}
|
||||
|
||||
public void GeProperty(string propertyName, string otherPropertyName) {
|
||||
Criterion = HqlRestrictions.GeProperty(propertyName, otherPropertyName);
|
||||
}
|
||||
|
||||
public void LtProperty(string propertyName, string otherPropertyName) {
|
||||
Criterion = HqlRestrictions.LtProperty(propertyName, otherPropertyName);
|
||||
}
|
||||
|
||||
public void LeProperty(string propertyName, string otherPropertyName) {
|
||||
Criterion = HqlRestrictions.LeProperty(propertyName, otherPropertyName);
|
||||
}
|
||||
|
||||
public void IsNotNull(string propertyName) {
|
||||
Criterion = HqlRestrictions.IsNotNull(propertyName);
|
||||
}
|
||||
|
||||
public void IsNotEmpty(string propertyName) {
|
||||
Criterion = HqlRestrictions.IsNotEmpty(propertyName);
|
||||
}
|
||||
|
||||
public void IsEmpty(string propertyName) {
|
||||
Criterion = HqlRestrictions.IsEmpty(propertyName);
|
||||
}
|
||||
|
||||
public void And(Action<IHqlExpressionFactory> lhs, Action<IHqlExpressionFactory> rhs) {
|
||||
lhs(this);
|
||||
var a = Criterion;
|
||||
rhs(this);
|
||||
var b = Criterion;
|
||||
Criterion = HqlRestrictions.And(a, b);
|
||||
}
|
||||
|
||||
public void Or(Action<IHqlExpressionFactory> lhs, Action<IHqlExpressionFactory> rhs) {
|
||||
lhs(this);
|
||||
var a = Criterion;
|
||||
rhs(this);
|
||||
var b = Criterion;
|
||||
Criterion = HqlRestrictions.Or(a, b);
|
||||
}
|
||||
|
||||
public void Not(Action<IHqlExpressionFactory> expression) {
|
||||
expression(this);
|
||||
var a = Criterion;
|
||||
Criterion = HqlRestrictions.Not(a);
|
||||
}
|
||||
|
||||
public void Conjunction(Action<IHqlExpressionFactory> expression, params Action<IHqlExpressionFactory>[] otherExpressions) {
|
||||
var junction = HqlRestrictions.Conjunction();
|
||||
foreach (var exp in Enumerable.Empty<Action<IHqlExpressionFactory>>().Union(new[] { expression }).Union(otherExpressions)) {
|
||||
exp(this);
|
||||
junction.Add(Criterion);
|
||||
}
|
||||
|
||||
Criterion = junction;
|
||||
}
|
||||
|
||||
public void Disjunction(Action<IHqlExpressionFactory> expression, params Action<IHqlExpressionFactory>[] otherExpressions) {
|
||||
var junction = HqlRestrictions.Disjunction();
|
||||
foreach (var exp in Enumerable.Empty<Action<IHqlExpressionFactory>>().Union(new[] { expression }).Union(otherExpressions)) {
|
||||
exp(this);
|
||||
junction.Add(Criterion);
|
||||
}
|
||||
|
||||
Criterion = junction;
|
||||
}
|
||||
|
||||
public void AllEq(IDictionary propertyNameValues) {
|
||||
Criterion = HqlRestrictions.AllEq(propertyNameValues);
|
||||
}
|
||||
|
||||
public void NaturalId() {
|
||||
Criterion = HqlRestrictions.NaturalId();
|
||||
}
|
||||
}
|
||||
|
||||
public enum HqlMatchMode {
|
||||
Exact,
|
||||
Start,
|
||||
End,
|
||||
Anywhere
|
||||
}
|
||||
|
||||
}
|
||||
92
src/Orchard/ContentManagement/IHqlQuery.cs
Normal file
92
src/Orchard/ContentManagement/IHqlQuery.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Orchard.ContentManagement.Records;
|
||||
|
||||
namespace Orchard.ContentManagement {
|
||||
|
||||
public interface IHqlQuery {
|
||||
IContentManager ContentManager { get; }
|
||||
IHqlQuery ForType(params string[] contentTypes);
|
||||
IHqlQuery ForVersion(VersionOptions options);
|
||||
IHqlQuery<T> ForPart<T>() where T : IContent;
|
||||
|
||||
IEnumerable<ContentItem> List();
|
||||
IEnumerable<ContentItem> Slice(int skip, int count);
|
||||
int Count();
|
||||
|
||||
IHqlQuery Join(Action<IAliasFactory> alias);
|
||||
IHqlQuery Where(Action<IAliasFactory> alias, Action<IHqlExpressionFactory> predicate);
|
||||
IHqlQuery OrderBy(Action<IAliasFactory> alias, Action<IHqlSortFactory> order);
|
||||
}
|
||||
|
||||
public interface IHqlQuery<out TPart> where TPart : IContent {
|
||||
IHqlQuery<TPart> ForType(params string[] contentTypes);
|
||||
IHqlQuery<TPart> ForVersion(VersionOptions options);
|
||||
|
||||
IEnumerable<TPart> List();
|
||||
IEnumerable<TPart> Slice(int skip, int count);
|
||||
int Count();
|
||||
|
||||
IHqlQuery<TPart> Join(Action<IAliasFactory> alias);
|
||||
IHqlQuery<TPart> Where(Action<IAliasFactory> alias, Action<IHqlExpressionFactory> predicate);
|
||||
IHqlQuery<TPart> OrderBy(Action<IAliasFactory> alias, Action<IHqlSortFactory> order);
|
||||
}
|
||||
|
||||
|
||||
public interface IAlias {
|
||||
string Name { get; }
|
||||
}
|
||||
|
||||
public interface IAliasFactory {
|
||||
IAliasFactory ContentPartRecord<TRecord>() where TRecord : ContentPartRecord;
|
||||
IAliasFactory ContentPartRecord(Type contentPartRecord);
|
||||
IAliasFactory Property(string propertyName, string alias);
|
||||
IAliasFactory Named(string alias); // returns an existing alias
|
||||
}
|
||||
|
||||
public interface IHqlSortFactory {
|
||||
void Asc(string propertyName);
|
||||
void Desc(string propertyName);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* query // IHqlQuery<ContentItem>
|
||||
* .Join<RoutePartRecord>().As("route") // IAlias(query), IAlias<T>(query<TP>), IAlias<TP,TR>(query<TP,TR>) alias name is implicit, there can't be any conflict
|
||||
* x => x.Where(route => route.
|
||||
* )
|
||||
*
|
||||
* query.Join<
|
||||
*
|
||||
* query: IAlias
|
||||
*
|
||||
*
|
||||
* IHqlQuery<T> ONLY, because we can have <ContentItem> by default, and the Records can't be used in expression though, thus having them
|
||||
* in the generic type is useless. _manager.HqlQuery<GammaPart>() will create a new query then apply ForPart<GammaPart>
|
||||
*
|
||||
* .Join<TRecord> is only valid for ContentPartRecord because they will resolve the fake civ.{TRecord} property
|
||||
* .Where<TRecord> is only valid for ContentPartRecord because they will resolve the fake civ.{TRecord} property
|
||||
* .Where( on => on.Named("foo"), x => x.Eq("Id", 1))
|
||||
*
|
||||
*
|
||||
* .Join( on => on.ContentPartRecord<FieldIndexPartRecord>().Property("IntegerFieldIndexRecords", alias: "integerFields")
|
||||
* .Where( on => on.Named("foo"), x => x.Eq("Id", 1))
|
||||
* .Where( on => on.ContentPartRecord<FieldIndexPartRecord>(), x => x.Eq("Id", 1))
|
||||
*
|
||||
*
|
||||
* Join(Action<IAliasFactory> alias)
|
||||
* Where(Action<IAliasFactory> alias, Action<IHqlExpression> predicate)
|
||||
*
|
||||
* Thus we can create aliases directly from the Where()
|
||||
*
|
||||
* IAlias {
|
||||
* ContentPartRecord<TRecord>() where TRecord : ContentPartRecord
|
||||
* Property(string propertyName, string alias)
|
||||
* Named(string alias) // returns an existing alias
|
||||
*
|
||||
* }
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -169,7 +169,11 @@
|
||||
<Compile Include="ContentManagement\ContentIdentity.cs" />
|
||||
<Compile Include="ContentManagement\ContentItemBehavior.cs" />
|
||||
<Compile Include="ContentManagement\ContentPartBehavior.cs" />
|
||||
<Compile Include="ContentManagement\DefaultHqlQuery.cs" />
|
||||
<Compile Include="ContentManagement\IHqlExpression.cs" />
|
||||
<Compile Include="ContentManagement\IHqlQuery.cs" />
|
||||
<Compile Include="ContentManagement\Handlers\DescribeMembersContext.cs" />
|
||||
<Compile Include="ContentManagement\IHqlCriterion.cs" />
|
||||
<Compile Include="ContentManagement\ISortFactory.cs" />
|
||||
<Compile Include="ContentManagement\DefaultContentDisplay.cs" />
|
||||
<Compile Include="ContentManagement\Drivers\ContentShapeResult.cs" />
|
||||
|
||||
Reference in New Issue
Block a user