Show/Hide Toolbars

TMS Aurelius Documentation

Navigation: Manipulating Objects

Updating Objects - Flush

Scroll Prev Top Next More

You modify objects using the TObjectManager method Flush. The state of all objects persisted in object manager is tracked by it. Thus, if you change any property of any object after it's loaded by the database, those changes will be updated to the database when Flush method is called. Consider the example below:

 

Customer1 := Manager1.Find<TCustomer>(CustomerId);
Customer1.Email := 'newemail@domain.com';
Customer2 := Manager1.Find<TCustomer>(Customer2Id);
Customer2.Email := 'another@email.com';
Manager1.Flush;

 

The Flush method will detect all objects which content has been changed since they were loaded, and then update them all in the database. In the example above, both customers 1 and 2 will have their e-mail changed.

 

It's possible that, by any reason, you want to update a detached object, in other words, an object that is not being tracked (persisted) by the manager. This might happen, for example, if you loaded an object with the manager, then destroyed the manager but kept the object reference (using TObjectManager.OwnsObjects = false). Or, for example, if you created the object instance yourself, and set its id property to a valid value. In this case the object is not in the manager, but you want to update the database using the object you have.

 

In this case, you can use Update method. This method will just take the passed transient instance and attach it to the TObjectManager. Then when you later call Flush, the changes will be persisted to the database. Note that when you call Update, no data is retrieved from the database. This means that the object manager doesn't know the original state of the object (data saved in database). The consequence is that all properties of the object passed to Update method will later be saved to the database when Flush is called. So you must be sure that all the persistent properties of the object have the correct value to be saved to the database.

 

Customer2 := Manager1.Find<TCustomer>(Customer2Id);

Manager1.OwnsObjects := false;

Manager1.Free;

Customer2.Name := 'Mary';
Customer2.Sex := tsFemale;
Manager2.Update(Customer2);

Manager2.Flush;

 

In the example above, a TCustomer object was loaded in Manager1. It's not attached to Manager2. When Update method is called in Manager2, all data in Customer2 object will be updated to the database, and it will become persistent in Manager2.

 

The cascades defined in Association attributes in your class are applied here. Any associated object or collection item that has TCascadeType.SaveUpdate defined will also be updated in database.

 

Merging

If you call Update method passing, say, Object1, but there was already another object attached to the TObjectManager with the same id (Object2), an exception will be raised. In this case, you can use Merge method to merge a transient object ("outside" the manager) into a persistent object ("inside" the manager).

 

Flushing a single object

Calling Flush might be slow if you have many entities in the manager. Flush will iterate through all entities and check if any of them is modified - and persist changes to the database. Alternatively, you can flush a single entity by using an overloaded version of Flush that receives a single object:

 

Customer1 := Manager1.Find<TCustomer>(CustomerId);
Customer1.Email := 'newemail@domain.com';
Customer2 := Manager1.Find<TCustomer>(Customer2Id);
Customer2.Email := 'another@email.com';
Manager1.Flush(Customer1);

 

In the example above, only changes made to Customer1 will be persisted. Customer2 changes will still be in memory only, and you would have to call Flush or Flush(Customer2) to persist the changes. This gives you finer control over what should be persisted and helps you increase performance of your code.

 

You must be careful, though, about associated objects. When you call Flush without specifying an object you are safe that all changes in the manager are persisted. You flushing a single object, associated objects might be flushed or not, depending on how the cascade options are set for that Association (or Many-Valued Association). If the association includes the TCascadeType.Flush, then it will also be flushed.