Self tracking “Poco’s” (self tracking data transfer objects)

4 בDecember 2009

tags: ,
9 comments

Recently I worked on a POC with the guidance of Bernie Almosni – Building a layer above the business entities (stored in a data base) with the use of an ORM (as the data access engine). During the process we encountered the disconnected scenario issue (it’ll describe in details below). The Self tacking DTO component was develop by Bernie and myself as a part of the POC – aimed at addressing  the disconnected scenario. We ended up with a generic framework not bound to specific ORM, that I think can be useful to many.

POC Requirements

  • The business entities are POCOs (Plain old CLR object).
  • We use inversion of control (specifically unity) so each of the business entities implement an interface. We work only with the interface in our business logic components.

ORM Context

Definition: this term is common for all ORMs that supports using POCOs as persistent entities. It describes the component that manages the entities by tracking the entities modifications. Then persist these specific modifications by sending SQL command to the database. In Entity Framework it is the ObjectContext and in NHibernate it is the Session.

The Disconnected Scenario

the flow:

  • Load an entity.
  • Send it to the client – N-Tier maybe by WCF. (the client doesn’t hold the ORM context so the entity is in a disconnected state).
  • The client modifies the entity.
  • The client sends the entity back to the server.
  • The server synchronizes the modifications with the database – this is the hard part since the server doesn’t know what modifications where made, if any. 

The Self Tracking DTO Framework

The framework enables the scenario above by using special objects – self tracking DTOs. The server works with the POCOs as usual but when it needs to send an entity to the client it uses a different object (a DTO).It implements the same interface but in addition provide special functionality:

  1. It Populates itself by a given server entity.
  2. Creates a new server side entity that contains its own value – by the common interface.
  3. Applies the modification made on it on a given server side object.
  4. Bonus: INotifyPropertyChange – implemented by the DTO implements so if you use WPF you get it out of the box.

The framework provides two two core interfaces:

1. The ISelfTrackingDataTransferObject interface

Provides the self tracking DTO needed functionality: 

void Populate(T entity) - Populates the DTO object by the given entity.

T Clone(bool getOriginalValue) - Creates a DTO clone – Server side object that holds the same value as the DTO.

void ApplyChanges(T enitity) - Simulate the changes made on the DTO object on the given entity ("plays" the changes).

2. The IDtoInstanceCreator interface

ISelfTrackingDataTransferObject<T> CreateDtoInstance<T>(T entity) – creates a new DTO instance by T and a given entity.

The class that implements this interface is the DTO factory – it create DTO instance by using the two parameters (T) and specific entity object. Note: if we use inheritance some times entity type is  derive from T and we need to create the DTO instance by the entity type.

Example

This example is part of the unit tests in the source, you can download and run it. I use Unity as my IoC so I use the UnityDataTransferObjectBase but it’s not mandatory, you can use the SelfTrackingDataTransferObjectBase as base class of the DTO object instead.

We have a simple entity that inherits from base class and has a matching interface:

public interface ISimpleObject : IObjectBase
{
int Id { get; set; }
string Name { get; set; }
}
public class ObjectBase : IObjectBase
{
public int Id { get; set; }
}

public class SimpleObject : ObjectBase ,ISimpleObject
{
public string Name { get; set; }
}

Now let’s look how at the DTO implementation:

[DataContract]
public class SimpleObjectDto : UnitySelfTrackingDataTransferObjectBase<ISimpleObject>, ISimpleObject
{
public SimpleObjectDto(IUnityContainer unityContainer) : base(unityContainer) { }
#region ISimpleObject Members
[DataMember]
private int _Id;
[DataMember]
private string _Name;

public int Id
{
get
{
return _Id;
}
set
{
Set("Id", ref _Id, value);
}
}

public string Name
{
get
{
return _Name;
}
set
{
Set("Name", ref _Name, value);
}
}

#endregion

protected override void SpecificPopulate(ISimpleObject entity, IDataTrasferObjectToEntityMapper dataTrasferObjectToEntityMapper)
{
_Id = entity.Id;
_Name = entity.Name;
}

protected override void SpecificGetValue(ISimpleObject entity, bool getOriginalValue, IDataTrasferObjectToEntityMapper dataTrasferObjectToEntityMapper)
{
entity.Id = RetrievePropertyValue<int>("Id", getOriginalValue);
entity.Name = RetrievePropertyValue<string>("Name", getOriginalValue);
}

protected override void SpecificApplyChanges(ISimpleObject entity, IDataTrasferObjectToEntityMapper dataTrasferObjectToEntityMapper)
{
}
}

Building the DTO is a technical action (no need to think here), in the source I have a readme guide that explains how do it and examples for each of the possible scenarios:

  • Entity holds only simple types.
  • Entity holds a reference to an Entity.
  • Entity holds a list of entities.

Now we implement the IDtoInstanceCreator interface, using unity. ( I use unity singleton which is just a singleton object holding UnityContainer)

public class MyDtoInstanceCreator : IDtoInstanceCreator
{
#region IDtoInstanceCreator Members

public ISelfTrackingDataTransferObject<T> CreateDtoInstance<T>(T entity)
{
return (ISelfTrackingDataTransferObject<T>)UnitySingleton.Instance.UnityContainer.Resolve<T>(DataTransferObjectsTester.STR_DTO);
}

#endregion
}

Setup our container:

UnitySingleton.Instance.UnityContainer.RegisterInstance<IDtoInstanceCreator>(new  MyDtoInstanceCreator());
UnitySingleton.Instance.UnityContainer.RegisterInstance<IUnityContainer>(UnitySingleton.Instance.UnityContainer);

//concrete types
UnitySingleton.Instance.UnityContainer.RegisterType<ISimpleObject, SimpleObject>();
//DTOS
UnitySingleton.Instance.UnityContainer.RegisterType<ISimpleObject, SimpleObjectDto>(STR_DTO);

Now we are ready to go!

First loading and sending the entity to the client:

ISimpleObject serverSideSimpleObject = LoadSimpleObject();
IDtoInstanceCreator dtoCreator = UnitySingleton.Instance.UnityContainer.Resolve<IDtoInstanceCreator>();
ISelfTrackingDataTransferObject<ISimpleObject> dtoObject = dtoCreator.CreateDtoInstance<ISimpleObject>(serverSideSimpleObject);
dtoObject.Populate(serverSideSimpleObject);
return dtoObject;

The client gets the DTO and ,modifies it and send it back to the server.The server is updates the entity state in data base (this is done inside ORM context scope):

using (IContext context = GetORMContext())
{
ISimpleObject serverSide = dtobject.Clone(true); //server side object holding the original values
context.Attach(serverSide); // attach the server side instance to context.
dtobject.ApplyChanges(serverSide);
context.SaveChanges();
}

 

Next Phases

  • Code Generator to generate the DTO class from the server side – I’m on it…
  • Support more actions on the collection – currently supports only add and remove.
  • More… I am open to your suggestions.

Entity Framework 4

EF4 that is currently in beta (part of VS 2010 beta) has a CTP with another very similar solution to the disconnected scenario (read about it here). This solution varies from the Self tracking DTO for example it uses the same objects in the client and server side. Note this solution is EF bound (cannot be used with other ORM) and currently it is only a CTP. In addition if you use Oracle DB you currently don’t have a working EF4 provider ( I believe this will change in the near future).

So that’s all, this code is open for you to use and upgrade.

Download it from SelfTrackingDTO in CodePlex.

Cheers Offir.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

9 comments

  1. Aby Mammen Mathew9 בDecember 2009 ב 7:07

    Offir, Its a good approach. However I was wondering why did you also want to capture notification events. Since you are maintaining a dictionary of old and new values.

    Reply
  2. Offir Shvartz10 בDecember 2009 ב 13:50

    The capture of the events are part of optimization we don’t want to continue passing on the object tree if the child object was not modified – the DTO object whats to know if his child object was modify or not – so the modification event is pass recursively to the parent: each DTO catch the event change is state and pass fires the event – so the father if exists we’ll catch the event and change it’s state.

    Reply
  3. Aby Mammen Mathew11 בDecember 2009 ב 15:17

    Offir, but aren’t you still passing it(object graph) across the wire. Since the client side (non .NET) cannot manage the events.

    Reply
  4. Offir Shvartz13 בDecember 2009 ב 23:35

    Aby , this solution is only for pure .NET clients. working with shared DLLs – the DTO’s are shared between the client and the server,

    Reply
  5. Roul Tip29 בDecember 2009 ב 17:58

    Great idea, but will this work over the long run?

    Reply
  6. Vydelat peníze na rulete2 בJanuary 2010 ב 18:34

    Great idea, but will this work over the long run?

    Reply
  7. Offir Shvartz19 בJanuary 2010 ב 14:17

    what do you mean long run ?
    this was tested with large hierarquical objects and work fine so could you be more specific

    Reply
  8. Kevin12 בMay 2010 ב 3:29

    Can’t find the download on “http://selftrakingdto.codeplex.com/”

    Can you point me to the download?

    Thanks,
    Kevin

    Reply
  9. Offir Shvartz28 בMay 2010 ב 12:28

    kevin
    just go to the source tab in the kink above and then choose download

    Reply