All operations on entities goes through an UnitOfWork.
A UnitOfWork allows you to access Entities and work with them. All modifications to Entities are recorded by the UnitOfWork, and at the end they may be sent to the underlying EntityStore by calling complete(). If the UoW was read-only you may instead simply discard() it.
A UoW differs from a traditional Transaction in the sense that it is not tied at all to the underlying storage resource. Because of this there is no timeout on a UoW. It can be very short or very long. Another difference is that if a call to complete() fails, and the cause is validation errors in the Entities of the UoW, then these can be corrected and the UoW retried. By contrast, when a Transaction commit fails, then the whole transaction has to be done from the beginning again.
A UoW can be associated with a Usecase. A Usecase describes the metainformation about the process to be performed by the UoW.
If a code block that uses a UoW throws an exception you need to ensure that this is handled properly, and that the UoW is closed before returning. Because discard() is a no-op if the UoW is closed, we therefore recommend the following template to be used:
UnitOfWork uow = uowf.newUnitOfWork(); try { ... uow.complete(); } finally { uow.discard(); }
This ensures that in the happy case the UoW is completed, and if any exception is thrown the UoW is discarded. After the UoW has completed the discard() method doesn't do anything, and so has no effect. You can choose to either add catch blocks for any exceptions, including exceptions from complete(), or skip them.