| Implementing Business Logic | 291
PersistInserted() method, you first have to invoke the base method and then have
to catch the PXLockViolationException exception that can be thrown in the base
method. If the exception is thrown, you have to check the new values for restriction
conditions to compose the appropriate error message for the UI. The framework raises
the PXLockViolationException exception in a general case if the database returns no
rows affected by the UPDATE command. When you catch the PXLockViolationException
exception, you have to check whether the restriction conditions take place. If you
have found that a restriction condition is false, throw the PXRowPersistingException
exception to return the appropriate error message to the UI. Otherwise, rethrow the
PXLockViolationException exception, because it was caused by another reason. On the
PXRowPersistingException exception, the transaction is rolled back and no record is
updated in the database. If no exceptions occur in PersistInserted(), the new value is
saved to the database.
For an ordinary data update without accumulators, you can check value restrictions
at different times before the data is updated in the database. In particular, on the
FieldVerifying and RowUpdating events, you can check the values for restrictions
at the model level, before the changes are saved to the PXCache object. On these
events, you typically implement validation of the values entered by the user. If you
need to check a value immediately before it is saved to the database, you can do this
on the RowPersisting event.
Using an Accumulator Attribute
An accumulator attribute triggers only for data records that have the Inserted status in
the cache object. Thus, you have to insert a data record into the cache to trigger an update
via the accumulator attribute. Once inserted, the data record gets the Inserted status
and maintains this status until it is saved to the database, even if you update the record in
the cache. When a user saves changes to the database, despite of that the record has the
Inserted status in the cache object, the framework generates the correct SQL statement
that updates the record or inserts it into the database. By default, if there is no record with
such a key in the database, a new one is inserted. If a record with these key values already
exists, it is correctly updated in the database because of the accumulator attribute.
When you invoke Update() on an Inserted record (inserted into the cache), the
record remains Inserted. When you invoke Update() on an unchanged record that
is retrieved from the database, the record becomes Updated, and the accumulator
won't trigger on this record. For more information on the statuses of data records, see
Modification of Data in a PXCache Object.
You can insert a data record with unique key values into the cache only once. The
framework won't insert the duplicate record. After you have inserted the record, use
Update() to modify its values in the cache within the current unsaved session.
In an accumulator attribute, you can specify which database operations are allowed. By
default, the accumulator attribute inserts a new record if it doesn't exist in the database
and updates an existing record, if any. To allow only insert or update operations, set the
InsertOnly or UpdateOnly property of the columns collection in the PrepareInsert()
method before invocation of columns.Update().