Sunday, 5 June 2011

Working with Entity Framework Profiler

I am very new to Entity Framework and only just getting my head around using it in my own projects.  But first I had an application with I knew was built on EF but it was exhibiting some concerning behaviour.  It was using a large number of queries to the database as determined from the SQL Profiler that comes with Sql Server 2005.  I felt this was a little excessive and suspected a SELECT N+1 Anti-Pattern was involved.

But how do I prove it?

I knew of a great sounded tool called EFProfiler and it sounded like a great way to get concrete evidence that the application was not playing nice with the database.

So I downloaded the trial version of EFProfiler to test my hypothesis.

But I run into a problem.

The documentation says I have to add a reference to a dll and in Application_Start in the Global.asax file, I have to add a single line of code.  This is a problem as I do not have access to the code and so I am very limited as to what I can change.

I consider what my options are and I recall that another great tool I make use of called Elmah has a means of easily slipping itself into a web application without needing to add code to reference it.  How it does this is by being an HttpModule.

HttpModules can be added to an application through the web.config which references the dll the module is conpiled and becomes part of the HttpApplication pipeline.  But my first read of the documentation, I can hook into events like BeginRefresh, but there is no indication that I can hook into Application_Start.

This is until I found this question on StackOverflow which lead me to an article on How to correctly use IHttpModule to handle Application_OnStart event.

So I quickly throw together a little project to create my own HttpModule.

Imports System.Web
Imports HibernatingRhinos.Profiler.Appender

Public Class EFProfilerModule
  Implements IHttpModule

  Private Shared ApplicationStarted As Boolean = False
  Private Shared ApplicationStartLock As New Object()

  Public Sub Dispose() Implements System.Web.IHttpModule.Dispose

  End Sub

  Public Sub Init(application As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init

    If Not ApplicationStarted Then
      SyncLock ApplicationStartLock
        If Not ApplicationStarted Then
          Me.OnStart(application)
          ApplicationStarted = True
        End If
      End SyncLock
    End If

    Me.OnInit(application)

  End Sub

  Public Overridable Sub OnStart(application As HttpApplication)

    EntityFramework.EntityFrameworkProfiler.Initialize()

  End Sub

  Public Overridable Sub OnInit(application As HttpApplication)

    ' put your module initialisation code here

  End Sub

End Class

Then all I needed to do was add two dll’s to the bin folder of the application.  The first being my dll with my customer HttpModule and the other being the file HibernatingRhinos.Profiler.dll.  Then I just added one line to the HttpModules section of the web.config.


<add type="CustomModule.EFProfilerModule" name="EFProfilerModule" />

I then fired up EFProf and navigated to the application and it worked!  EFProf started listing sessions and I could immediately see a number of red and grey dots signifying there were some issues found!

After just going to the login screen, signing in and taken to the home page (only two pages) the profiler picked up the following…

EFProf AnalysisNavigating to the login screen only listed two object contexts.  Signing in and loading the Home page produced 16 more object contexts.

I had my evidence and analysis from a commercial product!

My team are looking to use Entity Framework for data access in our projects and to help prevent ourselves from writing sub-optimal queries I will be advocating we purchase the full commercial version of EFProf as it takes all the pain away from detecting issues with your data access code and gives you guidance to fixing any problems.