Build a business entity procedure to support the ProDataSet
- Last Updated: February 11, 2026
- 4 minute read
- OpenEdge
- Version 13.0
- Documentation
Next, you will write the procedure that really
represents the dsOrder ProDataSet itself. This
is a variation of the OrderSupport.p procedure
you have written before. Call it OrderEntity.p.
The
goal of this part of the exercise is to create a business entity
object that manages dsOrder, expanding on the data
access procedure you created earlier. The following figure is a
sketch of the larger entity object.

The data access object
becomes part of a larger Order entity or business
object. The entity presents an API to the outside world that supports
specific types of access to the object. Any requests that need to
fill or save data use the business entity procedure as a gateway
to the data managed in the data access object.
Validation logic for saving changes and other business logic associated with the ProDataSet are also encapsulated within the entity so that the logic is always executed consistently whenever the ProDataSet is referenced. Now you are working with a true business object.
Procedure OrderEntity.p is a simple example of the business entity procedure. It manages the API the client window uses to test the procedures and coordinate access to the data. Later, you will attach validation logic to it as well.
There is not very much code in the procedure, partly because some of it is in OrderSource.p and partly because some of it will be moved to a new general purpose dynamic procedure to handle the whole save-changes process.
This
is the procedure that actually "owns" the ProDataSet instance on
the server side. It is this procedure's ProDataSet instance that
the FILL events and the Data-Sources are attached
to, and this instance that is actually filled with data to be passed
back to the client.
OrderEntity.p will
be run PERSISTENT in support of the client window,
as a server side procedure, either locally in the client process
or remotely. It first gets the handle of the ProDataSet and uses
this to set up a CLOSE trigger for the procedure
to clean up, as shown:
|
Remember that you cannot obtain a handle such
as hDataSet in the procedure main block and then
use it inside internal procedures that have a ProDataSet as a parameter
passed BY-REFERENCE. The handle will not be valid
in those procedures because they are pointing to the external ProDataSet
instance. This code gets the handle at the top of the main block
simply because there is a limitation in the DYNAMIC-FUNCTION syntax
that does not recognize the form DATASET dsOrder:HANDLE as
a parameter. (This is actually the same restriction that already
exists for buffer handle references.) Thus, you need to obtain the
handle in advance so that you can simply name the handle variable
in the function reference.
Next, the main block starts the
data access procedure and runs the attachDataSet function
for the local ProDataSet instance:
|
Because the methods in OrderSource.p operate on the ProDataSet instance passed into it, a single instance of the procedure itself could support any number of external instances of the ProDataSet. Therefore, in your application you could check whether there is already a running instance of a procedure such as this and use its handle if there is.
Remember that the fetchOrder procedure
in OrderSource.p is intended to be called from
its enclosing business entity procedure. Following is the version
of fetchOrder that a procedure outside the Order entity
calls to get an Order back. It defines its own OUTPUT parameter
explicitly BY-VALUE to assure that no other procedure
tries to pass in another ProDataSet instance BY-REFERENCE.
This is because it is the instance in OrderEntity.p that
has been attached to the FILL events and Data-Sources,
and only that instance can be filled properly.
Procedure fetchOrder turns
around and passes in the Order Number value to fetchOrder in OrderSource.p, along
with its own ProDataSet instance BY-REFERENCE. In
this way, it makes sure the local instance is used. For example:
|
Finally, there is a saveChanges procedure
in OrderEntity.p. This attaches the Data-Sources
to make sure they are there for the save, and then runs a new procedure
that you will write next, which captures all the standard save logic
in a single dynamic procedure. It then detaches the Data-Sources
from the ProDataSet, as shown:
|
As you can see, saveChanges is
actually entirely generic. It could operate on any ProDataSet, as
long as it knows the procedure handle of the data access procedure
that is stored in hSourceProc. If you had a generic
session manager that coordinated running procedures on the server,
your client could simply run saveChanges in that
session manager, which could use the ProDataSet parameter to identify
the ProDataSet type or name (dsOrder in this case),
and set hSourceProc to the data access procedure
for that ProDataSet. Since our simple example does not have such
a manager, we put saveChanges into the Order entity
itself.
This is the end of the code for OrderEntity.p.