Data object

Data object definition

Data objects are persistent objects which represents the domain. Data objects may have properties and indexed properties of primitive types, other data objects or reference codes.

Data objects have a unique identifier and a timestamp property which stores the time of the last update.

Data object interface

Data objects derive from the interface PmMda.Net.Dog.IDataObject which is described in the API.

Lightweight object

Each data object can have a lightweight representation. The lightweight representation has just a subset of the data object properties and is read only. This representations are called lightweight objects. Lightweight objects are used if just a subset of the information stored in the data objects is used. Lightweight objects avoid that unneeded data is sent over the wire.

Typical usage of lightweight objects is displaying a navigation tree in the user interface.

The condition in which a lightweight representation is generated is described in the tagged values.

The lightweight objects derive form the interface PmMda.Net.Dog.ILightweightObject which is described in the API.

Properties and indexed properties

The associations of a data object are either properties or indexed properties.

Properties

Properties are 1..1 or 1..0-1 associations. Properties may point to primitiv types, reference codes or other data objects.

Indexed proprties

Indexed Properties are 1..* associations. They may only point to other data objects. To save persistent indexed properties a foreign key reference from the item to the container is added to the item table.

Data Object Graph (DOG)

Modern client-server applications manipulate complex graphs of data objects. For example a contract with its positions and optional amendments is represented by a hierarchy of data information. These graphs are transferred from and to the client application. The user views data, edits it and commits the changes to the database through server functions. The patterns commonly found in the literature describe thoroughly how to implement simple data transfer objects (DTO) but ignore the complexity how graphs of objects should efficiently be transmitted between server and client components. The intended audience is software developers interested in using DOG or implementing their own variant.

A data object graph is represented by its root data object and the data object which are referenced by this root object.

Visitor pattern

The visitor pattern is used to traverse all data objects of a graph. I.e. if a root object has to be stored, the visitor is used to collects all data objects of this data object graph. For more information see here.

Persistence of data objects

The PmMda.Net.Dog.Persistence.PersistenceHandler is used to create, read, update and delete (CRUD) data objects.

Create

To create a data object, their default constructor is used. The identifier will be set to null to mark this data object as a new one. If the new data object is the root object of the DOG you can call PersistenceHandler.Store(myNewDataObject); to save the new object. An other possibility is to add the new data object to the root data object or another data object which is references by the root object. If the root object is stored (PersistenceHandler.Store(myRootDataObject);), the new data object will also be saved.

Read

To read a root data object from the database the method PersistenceHandler.Retrieve is used. To retrive a data object, its identifier and type must be specified. It is also possible to retrieve all data objects of a specified type.

Update

The update of a data object is done using the PersistenceHandler.Store method. The Store method calculates three lists:

This means the Store method ensures that just the data of the modified data object is stored. All other data is removed.

Delete

The PersistenceHandler.Delete method deletes the specified root object and all data objects which are referenced by the root objects.

Multiuser scenarios

In a multiuser environment, there are two models for updating persistent data: pessimistic and optimistic concurrency.
Pessimistic concurrency involves locking rows at the data source to prevent users from modifying data in a way that affects other users.
Optimistic concurrency does not lock a row when reading it. When a user wants to update a row, the application must determine whether another user has changed the row since it was read. Optimistic concurrency is generally used in environments with a low contention for data.

pmMDA.NET does currently only support the optimistic concurrency scenario.

An update of a data object graph requires the following steps:

  1. Retrieve the root object.
  2. Change the properties of the root object or a referenced data object.
    It is also possible to add or remove data objects to indexed properties.
  3. Store the root object.

The storeage of the root object may fail if another user has updated the same data object while we were changing the data! In that case your changed data is lost.

Example of an optimistic concurrency violation:
Time User 1 User 2
1 Reads the data objects.
2 Modifies the data objects.
3 Reads the data objects.
4 Stores the data objects
5 Modifies the data objects
6 Stores the data objects
--> The data objects were already modified by another transaction executed by user 1. The storange of the data objects will fail because of the optimistic concurrency violation and an exception is thrown.
--> The modifications made by user 2 are lost.

The same optimistic concurrency violation also occurs when user 1 would have deleted or inserted data objects from or to the dog.
It is impossible that an optimistic concurrency violation occurs if the users modify different data (i.e. different root objects) or if the users have only added new root objects.

If paging is used it is possible that the optimistic concurrency violation is reported while the user reads or modifies data. For more information see the chapter Paging >> Error handling.

Further information

Further information on how the persistence of data object is implemented can be found in the design documentation.