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 (relation) the field is part of will be dereferenced and the field mapped onto that relation is set to null (C#) or Nothing (VB.NET). Example:
var myOrder = new OrderEntity();
var myCustomer = new CustomerEntity("CHOPS");
myOrder.Customer = myCustomer; // A
myOrder.CustomerID = "BLONP"; // B
var referencedCustomer = 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 CustomerID of myOrder 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 relation will be set to null as well, as shown in the following example:
var myOrder = new OrderEntity(10254);
var myCustomer = myOrder.Customer; // A
myOrder.Customer = null; // B
At line A, lazy loading will fetch the customer related to order 10254. At line B, this customer is de-referenced. This means that the FK field of order creating this relation, 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 by intercepting 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 EntityBase. 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 the generated entity classes, preferably using the methods discussed in Adding your own code to the generated classes.
OnTransactionCommit and OnTransactionRollback are called on any entity participating in the transaction, no matter if there was an action on the entity or not. To check if an entity was saved during a transaction, test the entity's Fields.State property. If it's OutOfSync, the entity was saved.
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 at a later time.
The versioned field data is contained inside the entity and can pass with the entity 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.
var customer = new CustomerEntity("CHOPS");
customer.SaveFields("BeforeUpdate");
try
{
// show a form to the user which allows the user to
// edit the customer entity
ShowModifyCustomerForm(customer);
}
catch
{
// something went wrong. Entity can be altered. Roll back
// fields so further processing won't be affected by these
// changes which are not completed
customer.RollbackFields("BeforeUpdate");
throw;
}