Show/Hide Toolbars

TMS XData Documentation

Navigation: Service Operations

Server Memory Management

Scroll Prev Top Next More

When executing service operations, XData provides a nice automatic memory management mechanism that destroy all objects involved in the service operation execution. This makes it easier for you to implement your methods (since you mostly don't need to worry about object destruction) and avoid memory leaks, something that is critical at the server-side.

 

In general, all objects are automatically destroyed by XData at server-side. This means that when implementing the service, you don't need to worry to destroy any object. However, it's important to know how this happens, so you implement your code correctly, and also knowing that in some specific situations of advanced operations, the previous statement might not be completely true. So strictly speaking, the objects automatically destroyed by XData are the following:

 

Any object passed as parameter or returned in a function result (called param object or result object);

Any object managed by the context TObjectManager;

The context TObjectManager is also destroyed after the operation method returns.

Any associated object that is also deserialized or serialized together with the param object or result object;

 

Example

 

Suppose the following meaningless service implementation:

 

function TMyService.DoSomething(Param: TMyParam): TMyResult;
var
  Entity: TMyEntity;
begin
  Entity := TMyEntity.Create;
  Entity.SomeProperty := Param.OtherProperty;
  TXDataOperationContext.Current.GetManager.Save(Entity);
  Result := TMyResult.Create('test');
end;

 

You have three objects involved here:

 

Param, of type TMyParam and was created by XData;

function Result, of type TMyResult, being created and returned in the last line of service implementation;

Entity, of type TMyEntity, being created and then passed to context TObjectManager to be saved in the database.

 

You don't need to destroy any of those objects. Whatever objects are passed as param (Param) of function result are always destroyed by XData automatically. The context manager is automatically destroyed by XData, and since you have added an entity to it, it will be destroyed as well upon manager destruction (this is a TMS Aurelius feature, not XData).

 

 

Managed objects

 

To control what will be destroyed and avoid double destruction of same object instance (for example, if the same object is received as parameter and returned as function result), XData keeps a collection of object instances in a property named ManagedObjects, available in the TXDataRequestHandler object. You can access that property using the operation context:

 

TXDataOperationContext.Current.Handler.ManagedObjects

 

You can also add object to that collection in advance, to make sure the object you are creating is going to be destroyed eventually by XData. This can help you out in some cases. For example, instead of using a construction like this:

 

function TMyService.DoSomething: TMyResult;
begin
  Result := TMyResult.Create;
  try
    // do complex operation with Result object
  except
    Result.Free;
    raise;
  end;
end;

 

You could write it this way:

 

function TMyService.DoSomething: TMyResult;
begin
  Result := TMyResult.Create;
  // Make sure Result will be eventually destroyed no matter what
  TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result);

 
  // now do complex operation with Result object
end;

 

 

Specific cases

 

As stated before, in general you just don't need to worry, since the above rules cover pretty much all of your service implementation, especially if you use the context TObjectManager to perform database operations instead of creating your own manager. The situations where something might go wrong are the following:

 

1. If you create your own TObjectManager and save/retrieve entities with it that were also passed as parameter or are being returned in function result.

 

This will cause an Access Violation because when you destroy your object manager, the entities managed by it will be destroyed. But then XData server will also try to destroy those objects because they were passed as parameter or are being returned. To avoid this, you must set your TObjectManager.OwnsObjects property to false, or use the context TObjectManager so XData knows that the objects are in the manager and don't need to be destroyed. The latter option is preferred because it's more straightforward and more integrated with XData behavior.

 

2. If you are creating associated objects that are not serialized/deserialized together with your object

 

For example, suppose your method returns an object TCustomer. This TCustomer class has a property Foo: TFoo, but such property is not mapped in Aurelius as an association (or not marked to be serialized if TCustomer is a PODO). You then create a TFoo object, assign it to Foo property and return:

 

Result := TCustomer.Create;

Result.Foo := TFoo.Create;

 

Since the Foo property will not be serialized by the server, XData will not know about such object, and it will not be destroyed. So you must be sure to destroy temporary/non-mapped/non-serializable objects if you create them (or add them to ManagedObjects collection as explained above). This is a very rare situation but it's important that developers be aware of it.

 

There is a specific topic for client-side memory management using TXDataClient.