Skip to content

Building Queries

lukelukic edited this page Oct 20, 2020 · 7 revisions

As stated in introduction, queryable builder is made to simplify querying your datasource using query objects. Based on queryObject properties and their attributes, builder can filter, sort and paginate through your IQueyryable.

To query your datasource, builder uses the combination of predefined attributes, operators and conventions.

Further in text, whenever there is a source variable, it is of type IQueryable<Product> where Product is the following type:

public class Product 
{
    public decimal Price { get; set; }
    public string Name { get; set; }
    public string BrandName { get; set; }
}

Nullable properties

In most scenarios, you will want to use nullable types as your query object properties. When the property has the value of null, the builder simply ignores that property - it's not included in the predicate.

Consider the following scenario:

public class ProductQuery
{
    [QueryProperty]
    public decimal? Price { get; set; }
}
    var queryObject = new ProductQuery { Price = null };
    var result = source.BuildQuery(queryObject);

The result are going to be IQueryable with no predicate built - queryable with all the products will be returned. However, if we set the price property to some value, only products who'se price matches the value will be returned:

    var queryObject = new ProductQuery { Price = 250 };
    var result = source.BuildQuery(queryObject);

The query resulted with all the product having the price set exactly to 250.

Operators

There is a set of operators, exposed as enum for you to state the resulting predicate operation. They are all part of the ComparisonOperator enum:

public enum ComparisonOperator
{
    MoreThan,
    MoreThanOrEqualsTo,
    LessThan,
    LessThanOrEqualsTo,
    Equals,
    Contains,
    StartsWith,
    EndsWith,
    NotEqual
}

Each operator tells the builder how to treat the incomming property value against the actual datasource property. By default, if no operator is stated, Equals is used. When the queryObject property is not null, operator is going to dictate the underlying predicate.

public class ProductQuery
{
    [QueryProperty(ComparisonOperator.Contains)]
    public string Name { get; set; }
}
   var queryObject = new ProductQuery { Name = "test" };

Using the query object above, the resulting query will contain all the products containing "test" in their name, regardless of the text-case.

Available Query attributes

Currently, there are:

  1. QueryProperty,
  2. QueryProperties,
  3. WithQueryProperty
  4. WithAnyProperty

QueryProperty

Includes decorated property to a query building process.

Overloads:

  1. Default Constructor
public class ProductQuery
{
    [QueryProperty]
    public string Name { get; set; }
}
    var query = new ProductQuery { Name = "a" };
    var result = datasource.BuildQuery(query); 

QueryProperty setup:

  • Operator - Equals
  • Property to target - Name

Resulting query will include products filtered by their Name property.

  1. Parameterized constructor QueryProperty constructor takes up to 2 parameters - operator and propertyName. Property name represents a resulting type property name query is built against.
public class ComplexishProductQuery
{
    [QueryProperty(propertyName: "Price")]
    public decimal? CustomProp { get; set; }
    [QueryProperty(ComparisonOperator.Contains)]
    public string Name { get; set; }
    [QueryProperty(ComparisonOperator.StartsWith, "BrandName")]
    public string CustomProp2 { get; set; }
}
var query = new ComplexishProductQuery 
{
   CustomProp = 22,
   Name = "Fo",
   CustomProp2 = "Fa"
};
var result = datasource.BuildQuery(query);
//The resulting query would be best described with the follwing expression:
dataSource.Where(x => x.Name.Contains("Fo") && x.Price == 22 && x.BrandName.StartsWith("Fa"));

QueryProperties

Same rules apply as with QueryProperty except that it is designed to work to compare against several properties at the same time. Use it with at least 3 parameters - operator and two or more properties.

Example:

public class TestUserSearch
{
    [QueryProperties(ComparisonOperator.Contains, "FirstName", "Username")]
    public string Keyword { get; set; }
}
var result = datasource.BuildQuery(new { Keyword = "Fa" });
//The resulting query would be best described with the follwing expression:
dataSource.Where(x => x.FirstName.Contains("Fa") || x.Username.Contains("Fa"));

Clone this wiki locally