Concept: Create an query abstraction of OrchardDefaultQuery with fluent syntax

Tags: Orchard, Abstraction, Generics, Query, Fluent

Today I wanted to expose a custom query method in my service without exposing the whole orchard query. I wanted to abstract this Orchard defaultContentQuery because:

  • The user of the service doesn't have to know where the items are coming from (Orchard query language).
  • The service consumer can degrade the performance by using the query syntax incorrect.
  • The possiblity of code/logic being duplicated is a lot bigger when we expose the orchard query object.

My first version was were simply extensions methods on top of the Query<Part> methods but those were still "leaking" the orchard default query to the consumer.

Unfortunately I don't have a code formatter on my blog yet:( 

Usage example (In a Orchard command):

[CommandName("retrieve")]

[CommandHelp("retrieve")]
public void Retrieve()
{
      IList<MyTestPart> result = _myPartTestService.Query()
            .WithMyTestTitle("t")
            .WithRouteUrl("t")
            .ToList();

Context.Output.WriteLine(T("Item count" + result.Count()));
Context.Output.WriteLine(T("Done!"));

}

The implementation:

public interface ICustomPartQuery<T> where T : ContentPart {

      IList<T> ToList();
}

internal abstract class CustomQueryBase<T> : ICustomPartQuery<T> where T : ContentPart
{
       protected IContentQuery<T> _orchardQuery;

       protected CustomQueryBase(IContentManager contentManager) {
             _orchardQuery = contentManager.Query<T>();
       }

      public IList<T> ToList()
      {
            return _orchardQuery.List().ToList();
      }
}

public interface IMyPartQuery<T> : ICustomPartQuery<T> where T : ContentPart
{
      IMyPartQuery<T> WithMyTestTitle(string title);

      IMyPartQuery<T> WithRouteUrl(string name);
}

internal class MyCustomQuery : CustomQueryBase<MyTestPart>, IMyPartQuery<MyTestPart> {
      public MyCustomQuery(IContentManager contentManager) : base(contentManager) { }

      public IMyPartQuery<MyTestPart> WithMyTestTitle(string title)

      {
            _orchardQuery = _orchardQuery.Join<TitlePartRecord>().Where(s => s.Title.Contains(title));
            return this;
      }

      public IMyPartQuery<MyTestPart> WithRouteUrl(string name)
      {
           _orchardQuery = _orchardQuery.Join<AutoroutePartRecord>().Where(s => s.DisplayAlias.Contains(name));
           return this;
      }
}

public class MyPartTestService : IMyPartTestService
{
      private readonly IContentManager _contentManager;
       

      public MyPartTestService(IContentManager contentManager)
      {
            _contentManager = contentManager;
      }

     public IContentQuery<MyTestPart> MyTestPartsOrchardQuery()
     {
            return _contentManager.Query<MyTestPart>();
     }

     public IMyPartQuery<MyTestPart> Query()
     {
           return new MyCustomQuery(_contentManager);
     }
}

public interface IMyPartTestService : IDependency
{
      IMyPartQuery<MyTestPart> Query();
}