Data View Delegates: General Information
By default, when a data view object is requested by the UI or you invoke the Select() method on the object, the system executes the query specified in the data view declaration. However, you can define a dynamic query, which is an optional graph method (called the data view delegate) that is executed when the data view is requested. If no dynamic query is defined in the graph, MYOB Acumatica Framework executes the BQL statement from the data view declaration.
Learning Objectives
In this chapter, you will learn how to do the following:
- Define a data view delegate
- Define a dynamic query in a data view delegate
Applicable Scenarios
- You are constructing the query dynamically at run time by adding Where<> and Join<> clauses that depend on some condition, typically a filter.
- The query retrieves data fields that cannot be calculated declaratively by attributes—for instance, if you are retrieving values that are aggregated by calculated data fields.
- The result set has data records that are not retrieved from the database and are composed dynamically in code.
Definition of a Data View Delegate
To define the delegate for a data view, you should declare the data view and add a method that has the same name as the data view, except with a different case for the first letter. (For example, if the data view name is MyDataView, the name of the delegate must be myDataView.)
The delegate returns an IEnumerable
object, as shown in the code below.
// The SupplierProducts data view
[PXFilterable]
public SelectFrom<SupplierProduct>.
InnerJoin<Supplier>.On<Supplier.supplierID.IsEqual<
SupplierProduct.supplierID>>.
OrderBy<SupplierProduct.productID.Asc, SupplierProduct.supplierPrice.Asc,
SupplierProduct.lastPurchaseDate.Desc>.
View.ReadOnly SupplierProducts;
// The delegate for the SupplierProducts data view
protected virtual IEnumerable supplierProducts()
{
// Implement the dynamic query
}
The framework automatically adds the delegate by its name and invokes the method when the data view object is requested.
Implementation of a Data View Delegate
When you are implementing a data view delegate, we recommend that you store the results of its dynamic query in an object of the PXDelegateResult class and specify whether the query results are already filtered, truncated (to fit the page), and sorted. Repeated operations are not applied to the PXDelegateResult objects. So if you do not set IsResultFiltered, IsResultTruncated, or IsResultSorted to true, the platform will, respectively, filter, truncate, or sort the retrieved data after it is obtained from the database. The following code shows an example of how to use the PXDelegateResult class in a data view delegate.
protected virtual IEnumerable ardocumentlist()
{
PXSelectBase<BalancedARDocument> cmd =
new PXSelectJoinGroupBy<BalancedARDocument,
...
//Set the necessary sorting fields: use the key fields
OrderBy<Asc<BalancedARDocument.docType,
Asc<BalancedARDocument.refNbr>>>>
(this);
PXDelegateResult delegResult = new PXDelegateResult
{
IsResultFiltered = true,
IsResultTruncated = true,
IsResultSorted = true
}
foreach (PXResult<BalancedARDocument> res_record in cmd.SelectWithViewContext())
{
// add the code to process res_record
delegResult.Add(res_record);
}
return delegResult;
}
Execution of a Data View Delegate
A data view executes the delegate by using the following rules:
- If a delegate is not defined, the data view executes the BQL command.
- If a delegate is defined, the data view invokes the delegate and then does the
following:
- If the delegate returns
null
, the data view executes the BQL command. - If the delegate returns an object, the data view reorders the result according to
the
OrderBy
clause of the BQL command. However, this reordering of results is avoided if an object of the PXDelegateResult class is present within the data view delegate, its IsResultSorted property is set to true and the result is returned by using this object.
- If the delegate returns
In the delegate, you can execute any queries to get the needed data records. The result set
(PXResultset<> object) returned by the delegate must consist of
objects of the same DACs and in the same order as the classes are specified in the data view
type. Thus, in the example above, you can return a
PXResult<SupplierProduct>
object, but you cannot return a
PXResult<Supplier>
object. To return a Supplier
object from the delegate, you have to return the PXResult<SupplierProduct,
Supplier>
object from the method.
Construction of a Result Set
You can dynamically construct the result set that is returned by the data view. To construct a result set, you create an object of a generic PXResultset type and add PXResult objects to it.
The following code creates a result set of PXResult objects that contain
the joined data of three data access classes: Supplier
,
OrderLine
, and Product
.
// Create a PXResultset typed with the needed DACs
PXResultset<Supplier, OrderLine, Product> res =
new PXResultset<Supplier, OrderLine, Product>();
// Compose DAC objects, and set values for the needed fields
Supplier resultSupplier = new Supplier();
OrderLine resultLine = new OrderLine();
Product resultProd = new Product();
// Create a new PXResult object from DAC objects and add it to the result set
res.Add(new PXResult<Supplier, OrderLine, Product>(
resultSupplier, resultLine, resultProd));
A PXResultset collection implements the IEnumerable
interface; you can return the collection in a data view delegate.
protected virtual IEnumerable productRecords()
{
...
// In a data view delegate, you can return the entire result set
return res;
}