Specifying the type of a DynamicQuery resultset

A dynamic query is an un-typed projection of data. In the raw form, this query is returned in a list of object arrays. To have a typed projection, the a projectior func has to be specified. This can be done in two ways:

  1. Use the DynamicQuery.WithProjector<T>(Func<ProjectionRow, T> projectorFunc) method. The Func specified receives a ProjectionRow object, and converts it into an instance of type T. The WithProjector method returns a DynamicQuery<T> instance, instead of a DynamicQuery instance.
  2. Use the Query.Select(Expression<Func<T>> projection) method. This method is equal to query.Select(projection) where projection is one or more elements, however the projection lambda is converted into a Func<ProjectionRow, T> internally.

Fetching a DynamicQuery uses a projection fetch, so type converters and the like are taken into account.

A Dynamic query can be returned as one of the following result types:

  • List<object[]>. The projection is assumed to have one or more elements and every element's value is a position in the returned object array. Per row of the main query one object array is returned. Results of nested queries are seen as the result of an element and are placed at the position in the object array the nested query has in the projection.
  • List<T>. The projection of the query is assumed to have one field and every ProjectionRow is converted to a single value of type T. If T contains multiple fields or a CTor has to be called on T, use the WithProjector<T> Func/delegate approach of List<T> with a constructor delegate.
  • List<T> using the WithProjector delegate. Using the WithProjector<T> method or the Select(Expression<Func<>>) method, a Func (delegate) can be specified which contains the constructor call to convert the ProjectionRow into an instance of type T. The T instances are stored in a list which is returned. The Func/delegate can use index based indexers to obtain values, or use the method Get<T>(name) to obtain the value of property name as type T. The delegate is of type: Func<ProjectionRow, T>.

Examples

Below are three ways to define the same dynamic query. qf is the QueryFactory instance.

DynamicQuery, returning List<object[]>

var q = qf.Order
            .Where(OrderFields.CustomerId.StartsWith("C"))
            .OrderBy(OrderFields.CustomerId.Ascending())
            .Select(OrderFields.OrderId, OrderFields.CustomerId, 
                    OrderFields.EmployeeId, OrderFields.OrderDate)

DynamicQuery<T>, using WithProjector<T>, returning List<T>

var q = qf.Order
        .Where(OrderFields.CustomerId.StartsWith("C"))
        .OrderBy(OrderFields.CustomerId.Ascending())
        .Select(OrderFields.OrderId, OrderFields.CustomerId, 
                OrderFields.EmployeeId, OrderFields.OrderDate)
        .WithProjector(r => new
        {
            OrderId = (int)r[0],
            CustomerId = (string)r[1],
            EmployeeId = (int?)r[2],
            OrderDate = (DateTime?)r[3]
        });

DynamicQuery<T>, using .Select(Expression<Func<>>), returning List<T>

var q = qf.Order
        .Where(OrderFields.CustomerId.StartsWith("C"))
        .OrderBy(OrderFields.CustomerId.Ascending())
        .Select(() => new
        {
            OrderId = OrderFields.OrderId.ToValue<int>(),
            CustomerId = OrderFields.CustomerId.ToValue<string>(),
            EmployeeId = OrderFields.EmployeeId.ToValue<int?>(),
            OrderDate = OrderFields.OrderDate.ToValue<DateTime?>()
        });