Additional features

FK-PK synchronization

Foreign key synchronization with a related Primary key field is done automatically in code.

For example:

  • Instantiate a Customer entity, add a new Order class instance to its Orders collection. Now add OrderDetails class instances to the new Order's OrderDetails collection. You can simply save the Customer entity and all included new/'dirty' entities will be saved and any PK-FK relations will be updated/synchronized automatically.
  • Alter the Customer object in the example above, and save the Order object. The Customer object is saved first, then the Order and then the OrderDetails objects with all PK-FK values being synced

This synchronization of FK-PK values is already done at the moment you set a property to a reference of an entity object, for example myOrder.Customer = myCustomer, if the entity (in this case myCustomer) is not new, or if the PK field(s) aren't sequenced fields when the entity is new. Synchronization is also performed after a save action, so identity/sequenced columns are also synchronized.

If you set a foreign key field (for example Order.CustomerID) to a new value, the referenced entity by the foreign key (relationship) the field is part of will be dereferenced and the field mapped onto that relationship is set to null (C#) or Nothing (VB.NET).


OrderEntity myOrder = new OrderEntity();
CustomerEntity myCustomer = new CustomerEntity("CHOPS");
myOrder.Customer = myCustomer;  // A
myOrder.CustomerID = "BLONP";   // B
CustomerEntity referencedCustomer = myOrder.Customer; // C
Dim myOrder As New OrderEntity()
Dim myCustomer As New CustomerEntity("CHOPS")
myOrder.Customer = myCustomer   ' A
myOrder.CustomerID = "BLONP"    ' B
Dim referencedCustomer As CustomerEntity = myOrder.Customer ' C

After line 'A', myOrder.CustomerID will be set to "CHOPS", because of the synchronization between the PK of myCustomer and the FK of myOrder. At line 'B', the foreign key field myOrder.CustomerID is changed to a new value, BLONP. Because the FK field changes, the referenced entity through that FK field, myCustomer, is dereferenced and myOrder.Customer will return null/Nothing. Because there is no current referenced customer entity, the variable referencedCustomer will be set to null / Nothing at line 'C'.

The opposite is also true: if you set the property which represents a related entity to null (Nothing), the FK field(s) forming this relationship will be set to null as well, as shown in the following example:

PrefetchPath2 path = new PrefetchPath2(EntityType.OrderEntity);
OrderEntity myOrder = new OrderEntity(10254);
adapter.FetchEntity(myOrder, path);     // A
myOrder.Customer = null;    // B
Dim path As New PrefetchPath2(EntityType.OrderEntity)
Dim myOrder As New OrderEntity(10254)
adapter.FetchEntity(myOrder, path)      ' A
myOrder.Customer = Nothing      'B

At line A, the prefetch path loads the related Customer entity together with the Order entity with PK value 10254. At line B, this Customer is de-referenced. This means that the FK field of myOrder creating this relationship, myOrder.CustomerId, will be set to null (Nothing). So if myOrder is saved after this, NULL will be saved in the field Order.CustomerId.

Extending an entity to intercept activity calls

During the entity's lifecycle and the actions in which the entity participates, various methods of the entity are called, and which might be a good candidate for your own logic to be called as well, for example when the entity is initialized you might want to do your own initialization as well.

The entity classes offer a variety of methods for you to override to perform tasks in various situations. These methods all start with On and can be found in the LLBLGen Pro reference manual in the class EntityBase2. The entity classes also offer events for some situations, like the Initializing and Initialized events.

If you want to perform a given action when one of these methods are called, you can override them in a partial class of one of the generated entity classes, preferably using the methods discussed in Adding your own code to the generated classes.

IDataErrorInfo implementation

Entity classes implement IDataErrorInfo. To utilize this interface in your own code, two methods are available: SetEntityError and SetEntityFieldError, which allows external code to set the error of a field and/or entity. If true is passed for the argument append of SetEntityFieldError, the error message is appended to an existing message for that field using a semi-colon as separator.

Entity field validation, which is triggered by setting a field to a value, sets the field's error message if an exception occurs or when the custom field validator fails. The error message is appended to an existing message.

Field data versioning

One innovative feature of LLBLGen Pro is its field data versioning. The fields of an entity, say a CustomerEntity, can be versioned and saved under a name inside the entity object itself. Later, you can decide to rollback the entity's field values to the values saved under that name.

The versioned field data is contained inside the entity and can pass with the entity over remoting borders and is saved inside the XML produced by WriteXml(). All fields are versioned at once, you can't version a field's values individually.

The following example loads an entity, saves its field values, alters them and then rolls them back, when an exception occurs.

CustomerEntity customer = new CustomerEntity("CHOPS");
// fetch customer here..
    // show a form to the user which allows the user to
    // edit the customer entity
    // something went wrong. Entity can be altered. Roll back
    // fields so further processing won't be affected by these
    // changes which are not completed
Dim customer As New CustomerEntity("CHOPS")
' fetch customer here..
    ' show a form to the user which allows the user to
    ' edit the customer entity
    ' something went wrong. Entity can be altered. Roll back
    ' fields so further processing won't be affected by these
    ' changes which are not completed
End Try