/// <summary>
/// Tests a more complex usage of the fieldcompareset predicate: Get employee with the last order they closed.
/// SELECT E.EmployeeID, O.OrderID
/// FROM Employees E INNER JOIN Orders O
/// ON E.EmployeeID = O.EmployeeID
/// WHERE O.OrderId =
/// (
/// SELECT TOP 1 OrderId FROM Orders
/// WHERE EmployeeID = E.EmployeeID
/// ORDER BY OrderDate DESC
/// )
/// </summary>
[Test]
public void FieldCompareSetTestComplex()
{
DataAccessAdapter adapter = new DataAccessAdapter();
ResultsetFields fields = new ResultsetFields(2);
fields.DefineField(EmployeeFieldIndex.EmployeeId, 0, "EmployeeId", "E");
fields.DefineField(OrderFieldIndex.OrderId, 1, "OrderId", "O");
try
{
IRelationPredicateBucket bucket = new RelationPredicateBucket();
bucket.Relations.Add(EmployeeEntity.Relations.OrderEntityUsingEmployeeId, "E", "O", RelationWeaknessHint.None);
bucket.PredicateExpression.Add(new FieldCompareSetPredicate(
EntityFieldFactory.Create(OrderFieldIndex.OrderId), null,
EntityFieldFactory.Create(OrderFieldIndex.OrderId), null,
SetOperator.Equal,
new FieldCompareExpressionPredicate(
EntityFieldFactory.Create(OrderFieldIndex.EmployeeId), null,
ComparisonOperator.Equal,
new Expression(fields[0])),
null,
"O",
1,
new SortExpression(SortClauseFactory.Create(OrderFieldIndex.OrderDate, SortOperator.Descending))
));
DataTable tlist = new DataTable();
adapter.FetchTypedList(fields, tlist, bucket);
Assert.AreEqual(9, tlist.Rows.Count);
}
finally
{
adapter.Dispose();
}
}
(functionality is shown in adapter, but it's available to selfservicing as well)
The FieldCompareSetPredicate has per template group 10 constructors. It's a bit much to add it to the PredicateFactory class, as that would inflate that class with a lot of code if the project is a bit large. So I'm thinking of not included this predicate in that class.
SetOperator has also operators like Exists, EqualAny, GreaterEqualAll etc., and combined with the expression support for both field compared as well as the field in the subquery (which can contain subqueries), I think the filtering options are limitless now and there won't be a lot of situations where you need a stored proc or view to get things done
(ex: you can now produce:
... WHERE ((Foo + Bar) * 3) > ALL (Select (Bar + 2) FROM bla WHERE...)
etc.)
I'm not completely sure, but with this power the filtering of LLBLGen Pro looks like one of the most powerful at the moment
I hope to have the beta next week, as some things still have to be implemented (but we're getting close now
)
Another example: (which can be done today already, with a join (which is more efficient in most cases, but just for testing's sake
))
/// <summary>
/// Tests the FieldCompareSetPredicate using a simple subquery.
/// select * from products where productid not in (select productid from [order details])
/// or: all products which are not sold in an order.
/// </summary>
[Test]
public void FieldCompareSetTestSimple()
{
DataAccessAdapter adapter = new DataAccessAdapter();
try
{
IRelationPredicateBucket bucket = new RelationPredicateBucket();
bucket.PredicateExpression.Add(new FieldCompareSetPredicate(
EntityFieldFactory.Create(ProductFieldIndex.ProductId), null,
EntityFieldFactory.Create(OrderDetailsFieldIndex.ProductId), null,
SetOperator.In,
null,
true));
EntityCollection notSoldProducts = new EntityCollection(new ProductEntityFactory());
adapter.FetchEntityCollection(notSoldProducts, bucket);
Assert.AreEqual(3, notSoldProducts.Count);
}
finally
{
adapter.Dispose();
}
}