And... we're done!
/// <summary>
/// Tests the new ScalarQueryExpression object by fetching 4 fields from customer and appending 2 scalar expression subqueries:
/// the # of orders and the latest order date.
/// </summary>
[Test]
public void ScalarQueryExpressionTest()
{
ResultsetFields fields = new ResultsetFields( 6 );
fields.DefineField( CustomerFields.CustomerId, 0 );
fields.DefineField( CustomerFields.CompanyName, 1 );
fields.DefineField( CustomerFields.City, 2 );
fields.DefineField( CustomerFields.Region, 3 );
fields.DefineField( new EntityField2( "NumberOfOrders",
new ScalarQueryExpression( OrderFields.OrderId.SetAggregateFunction( AggregateFunction.Count ),
(CustomerFields.CustomerId == OrderFields.CustomerId) ) ), 4 );
fields.DefineField( new EntityField2( "LastOrderDate",
new ScalarQueryExpression( OrderFields.OrderDate.SetAggregateFunction( AggregateFunction.Max ),
(CustomerFields.CustomerId == OrderFields.CustomerId))), 5);
DataTable results = new DataTable();
using(DataAccessAdapter adapter = new DataAccessAdapter())
{
adapter.FetchTypedList(fields, results, new RelationPredicateBucket(CustomerFields.Country=="USA"), 0,
new SortExpression(CustomerFields.CompanyName | SortOperator.Ascending), true);
}
ResultsetViewer viewer = new ResultsetViewer();
viewer.BindDataTable(results);
viewer.ShowDialog();
}
Gives this query:
SELECT [Northwind].[dbo].[Customers].[CustomerID] AS [CustomerId],
[Northwind].[dbo].[Customers].[CompanyName],
[Northwind].[dbo].[Customers].[City],
[Northwind].[dbo].[Customers].[Region],
(
SELECT TOP 1 COUNT([Northwind].[dbo].[Orders].[OrderID]) AS [OrderId]
FROM [Northwind].[dbo].[Orders]
WHERE
(
[Northwind].[dbo].[Customers].[CustomerID] = [Northwind].[dbo].[Orders].[CustomerID]
)
) AS [NumberOfOrders],
(
SELECT TOP 1 MAX([Northwind].[dbo].[Orders].[OrderDate]) AS [OrderDate]
FROM [Northwind].[dbo].[Orders]
WHERE
(
[Northwind].[dbo].[Customers].[CustomerID] = [Northwind].[dbo].[Orders].[CustomerID]
)
) AS [LastOrderDate]
FROM [Northwind].[dbo].[Customers]
WHERE
(
(
[Northwind].[dbo].[Customers].[Country] = @Country1
)
)
ORDER BY [Northwind].[dbo].[Customers].[CompanyName] ASC
Yay!
I jam it through the same code as the FieldCompareSetPredicate uses, so it just creates a subquery, and therefore the TOP 1 is there, as I want to have it to have one value only in all situations.
As this is a normal IExpression class, you can use it everywhere you want to use an IExpression, so you can assign it to a field's ExpressionToUse property and use it in a DbFunctionCall, in another expression, in a filter ... etc.
Keep in mind that these queries can be inefficient, especially in where clauses. So use them only in select lists if possible