Registering with AssociationChanged event on POCO with change tracking proxy

Entity Framework 4.0 allows you to use POCO objects for your entities defined on the model. Suppose one of the POCO entity has a collection property and you want to be notified when a new entity is added or removed from the collection. How do we get notified when the collection is changed? Well if your poco objects supports change tracking proxy, you can be assured that Entity Framework will initialize your collection to EntityCollection. You can use EntityCollection’s AssociationChanged event to find out what got added or removed. EntityCollection  has been around since version 1 and it is currently the collection that is used if you use the default code generation. Some of the benefit of using EntityCollection includes.

1. Support for lazy loading.

2. Fixing navigation references. Meaning when you say customer.Orders.Add(order); order.Customer would point to the correct customer.

Although relying on internal details is not a good way to code because may be down the road, Entity Framework may not initialize the collection to EntityCollection when a change tracking proxy is created for poco object. This is basically a hack which allows you to register for notifications on the collection.

In this example we will walk through a simple example of how to register with AssociationChanged event for POCO objects that supports ChangeTracking Proxy.

Suppose we have the following model.

image

To ensure EF can create change tracking proxy for our poco objects we must mark all our properties as virtual and the collection property must return ICollection<T>.  Below is the code for the above model.

image

 

For the ObjectContext, we need to register with StateChanged event which is the event that occurs when an object is added to the context. In that event we access the bank account object and registers with the Associationchanged event for its Transactions Collection property. Inside the AssociationChanged event we check if the transaction is Withdrawl or Deposit and update the Balance property on the BankAccount object appropriately. Code below shows the code for the ObjetContext.

image

Notice in the StateChanged , I am assigning the BankAccount reference to dynamic keyword so i can make use of late binding. after that I check if the object being added is BankAccount object and also if the Object implements IEntityWithChangeTracker. The Bank Account object will only implement IEntityWithChangeTracker if it uses change tracking proxy and if object implements IEntityWithChangeTracker then we know the collections are initialized to EntityCollection. Inside the StateChanged event we register with AssociationChanged event for Transactions Collection property.

The AccountChanged method reduces the balance if the transaction is withdrawl otherwise adds the amount deposited to the current balance on the bankaccount object.

To test the code we can create a  bankaccount object, add a withdrawl and deposit transaction and then print out the current balance.

image

 

In the above code, we use CreateObject method to ensure we get a proxy object for the BankAccount, Withdrawl and Deposit entity. we add the two transactions to the transactions collection and print the current balance.

Note: You would not receive change notifications to collection if you do not get a change tracking proxy. This could be because you have instantiated your objects using the new keyword, poco objects does not meet the requirement for proxy or you have proxy creation turned off.

No Comments