Scalar query creation and fetching
Queries can be converted to scalar queries. This can be necessary when a query is guaranteed to return a single value and that value has to be used in e.g. a predicate. To convert a query to a scalar query, use any of the following methods
- 
Append the query with .CountRow() (or CountRowBig()). This will
convert the query in a SELECT COUNT(*) FROMquery construct. For EntityQuery<T> instances, it will simply replace the original entity projection with aCOUNT(*). For DynamicQueries, it will wrap the query.
- 
Append the query with an Aggregate method The following are
aggregate methods, which all require a parameter (field
or expression)
- Avg(parameter). Will produce the average of the parameter element over the query called on. Distinct variant: AvgDistinct
- Count(parameter). Will produce the count of the parameter element over the query called on. Distinct variant: CountDistinct.
- 
CountBig(parameter). Same as Count(parameter) but now
uses COUNT_BIG(), a SQL Server specific aggregate function
- Max(parameter). Will produce the max value of the parameter element over the query called on.
- Min(parameter). As Max() but now will produce the min value of the parameter element.
- StDev(parameter). Will produce the standard deviation of the parameter element over the query called on. Distinct variant: StDevDistinct()
- Sum(parameter). Will produce the summation of the parameter element over the query called on. Distinct variant: SumDistinct()
- Variance(parameter). Will produce the variance of the parameter element over the query called on. Distinct variant VarianceDistinct()
 
- Call .ToScalar() on the query. This will produce a scalar query with the first element in the projection as the field to return. An overload accepts a boolean whether to specify a row limit clause.
To enforce a row limit, the method .ForceRowLimit() can be called on a scalar query expression. Row limits are required if the scalar query can potentially return multiple elements and just 1 element is required.
A scalar query can also result in a NULL value if there are no rows for instance. To anticipate on this, always make sure
you use a nullable return type in your FetchScalar() calls. This is also true for Any() queries, even though it might look
the query will always result in a value: due to the way the Any call is converted into SQL it can be that there aren't rows in the 
targeted table / view and therefore a NULL value is returned. 
Fetching Scalar queries
Fetching scalar queries is possbly by using a wrapping Select() call. Below are several examples of constructing and fetching scalar queries directly.
var qf = new QueryFactory();
// Scalar query which fetches a boolean using Any(). 
var q = qf.Create().Select(qf.Customer.Where(CustomerFields.CustomerId.Equal("CHOPS")).Any());
var exists = adapter.FetchScalar<bool?>(q) ?? false;
// Another scalar query using Any() fetching a boolean.
var q = qf.Create()
      .Select(qf.Customer.Where(CustomerFields.Country.Equal("Germany"))
            .Any(CustomerFields.CustomerId.Equal("ALFKI")));
var exists = adapter.FetchScalar<bool?>(q) ?? false;
// Fetching the total of all orders. 
var q = qf.Create()
    .Select(qf.Customer.As("C")
        .Select(CustomerFields.CustomerId,
            qf.Order
                .CorrelatedOver(OrderEntity.Relations.CustomerEntityUsingCustomerId)
                .Select(qf.OrderDetail
                    .CorrelatedOver(OrderDetailEntity.Relations.OrderEntityUsingOrderId)
                    .Select(OrderDetailFields.Quantity * OrderDetailFields.UnitPrice)
                    .Sum().As("OrderTotal"))
                .Sum().As("TotalAllOrders"))
            .Max());
var result = adapter.FetchScalar<decimal?>(q) ?? 0.0M;
// Fetching the rowcount of a query defined separately. 
var q = qf.Create()
    .Select(CustomerFields.CustomerId, CustomerFields.CompanyName, 
            OrderFields.OrderId, OrderFields.OrderDate)
    .From(qf.Customer.InnerJoin(CustomerEntity.Relations.OrderEntityUsingCustomerId));
var count = adapter.FetchScalar<int>(qf.Create().Select(q.CountRow()));
var qf = new QueryFactory();
// Scalar query which fetches a boolean using Any(). 
var q = qf.Create().Select(qf.Customer.Where(CustomerFields.CustomerId.Equal("CHOPS")).Any());
var exists = new TypedListDAO().GetScalar<bool?>(q, null) ?? false;
// Another scalar query using Any() fetching a boolean.
var q = qf.Create()
      .Select(qf.Customer.Where(CustomerFields.Country.Equal("Germany"))
            .Any(CustomerFields.CustomerId.Equal("ALFKI")));
var exists = new TypedListDAO().GetScalar<bool?>(q, null) ?? false;
// Fetching the total of all orders. 
var q = qf.Create()
    .Select(qf.Customer.As("C")
        .Select(CustomerFields.CustomerId,
            qf.Order
                .CorrelatedOver(OrderEntity.Relations.CustomerEntityUsingCustomerId)
                .Select(qf.OrderDetail
                    .CorrelatedOver(OrderDetailEntity.Relations.OrderEntityUsingOrderId)
                    .Select(OrderDetailFields.Quantity.Mul(OrderDetailFields.UnitPrice))
                    .Sum().As("OrderTotal"))
                .Sum().As("TotalAllOrders"))
            .Max());
var result = new TypedListDAO().GetScalar<decimal?>(q, null) ?? 0.0M;
// Fetching the rowcount of a query defined separately. 
var q = qf.Create()
    .Select(CustomerFields.CustomerId, CustomerFields.CompanyName, 
            OrderFields.OrderId, OrderFields.OrderDate)
    .From(qf.Customer.InnerJoin(CustomerEntity.Relations.OrderEntityUsingCustomerId));
var count = new TypedListDAO().GetScalar<int?>(qf.Create().Select(q.CountRow()), null);