The EntityDataSource is a control you can use on your ASP.NET Pages to connect ASP.NET Controls like the GridView to an ADO.NET Entity Framework Data Source. Its the easiest way to display, add or modify data via the Entity Framework.

ObjectContext Lifetime with the EntityDataSource

The default behavior of EntityDataSource is to create a new ObjectContext for every page request and dispose the context again at the end of the page lifecycle.

The EntityDataSource control also allows you to provide your own ObjectContext by using the ContextCreating and ContextDisposing events. There is a good article on msdn that describes the Object Context Life-Cycle managed by the EntityDataSource.

The described approach works fine. It also allows you to use the ObjectContext across page requests. This can be useful when you don’t have data that changes frequently and if you want to save on lots of short living objects that are created when accessing the same data all over again. A description about that can be found in my recent article about the ADO.NET Entity Framework.

Memory Leak with PropertyChangeEventHandler

I created a simple ASP.NET MVC Sample Application where my page hosts a GridView that is linked with an EntityDataSource. I implemented the event handlers as described in the msdn article and passed an application scope instance of my entity classes to the Context property of the EntityDataSource. The actual ObjectContext is provided by my MVC Controller and put into the ViewData. Here are some code-snippets showing how to use my own ObjectContext and how to disable ObjectContext disposal at the end of the page lifecycle:

protected void EntityDataSource1_ContextCreating(object sender, System.Web.UI.WebControls.EntityDataSourceContextCreatingEventArgs e)
{
  e.Context = (System.Data.Objects.ObjectContext)this.ViewData["GridData"];
}
protected void EntityDataSource1_ContextDisposing(object sender, System.Web.UI.WebControls.EntityDataSourceContextDisposingEventArgs e)
{
  e.Cancel = true;
}

I ran a simple Visual Studio Load Test against this page – requesting the same page for a couple of minutes with a single user. Monitoring the memory showed me a growing Gen2 Heap.

Memory Leak in Gen2 Heap
Memory Leak in Gen2 Heap

With the help of several memory snaphots which I took within the same test period, I identified the growing class to be System.ComponentModel.PropertyChangedEventHandler.

Growing instances of PropertyChangedEventHandler
Growing instances of PropertyChangedEventHandler

Walking the referrer tree of those objects brought me to my EntityObject class (Customers) that I used on the page. The interesting detail here is that I only had 25 Entity Objects (that was my page size of the GridView and during my test I only tested the first grid page). Those 25 Entity Objects however had references to 165.800 event handler objects:

Referrer Tree from PropertyChangedEventHandler to EntityObject
Referrer Tree from PropertyChangedEventHandler to EntityObject

Why so many PropertyChangedEventHandler’s?

It turned out that the EntityDataSource is registering a PropertyChangedEventHandler for every property on the EntityObject. I had 25 objects on a page with 13 properties each. Every page request therefore created 325 event handler objects. As we do not allow the EntityDataSource to dispose the ObjectContext (we set e.Cancel to true in the ContextDisposing event handler) – those EventHandlers were never disposed.

The problem of course is that the EntityDataSource has to remove its event handlers regardless whether the ObjectContext will be disposed or not. I did some research on how to programmatically “encourage” the release – but haven’t yet found anything in the documentation nor by browsing through the ADO.NET EntityFramework code (using Reflector).

Conclusion

Be aware of the side effects when using your own ObjectContext. If you use it over a too long period of time with an EntityDataSource you will run into the described memory leak.