MvcMiniProfiler is a lean and mean mini profiler for MVC 3 that shows the profiling results on each page displayed at runtime. Besides the custom steps you can seed everywhere in your code it supports database profiling as well. Out of the box are supported ado.net, Linq to SQL and Entity Framework. LLBLGenPro, my favorite ORM, isn’t supported though and it won’t work just like that.
Luckily, it turns out, it requires just a little effort to integrate MvcMiniProfiler into LLBLGenPro.
How does MvcMiniProfiler database profiling works
The way it works is that it wraps DbConnection, DbCommand and other Db[Stuff] and thus records the execution time by tracking their inner workings. Here is an example for MvcMiniProfiler documentation about how to start:
public static DbConnection GetOpenConnection()
var cnn = CreateRealConnection(); // A SqlConnection, SqliteConnection ... or whatever
// wrap the connection with a profiling connection that tracks timings
return MvcMiniProfiler.Data.ProfiledDbConnection.Get(cnn, MiniProfiler.Current);
If client calls DbConnection.CreateCommand on an ProfiledDbConnection instance returned from previous method it will get a wrapped whatever command original connection returns and so on. There is also a way to manually create DbCommand through ProfiledDbCommand constructor.
The support for Linq To SQL and Entity Framework is done in a similar manner.
This gets us to the point, why can’t I just use the same approach with LLBLGenPro?
Integrate MvcMiniProfiler with LLBLGenPro – why doesn’t work with same approach
The major problem with LLBLGenPro and MvcMiniProfiler integration is that LLBLGenPro doesn’t use DbConnection.CreateCommand method to create commands from existing connection. Instead it creates an instance of proper DbCommand derived class and assigns a connection to it. Thus it won’t work because it would try to assign a ProfiledDbConnection to a i.e. SqlCommand class.
So a bit more work is required to match them.
The code for adapter scenario
1. Create a DynamicQueryEngine derived class. Note: this class is database specific, thus if you work with i.e. SQL Server you’ll find it in SD.LLBLGen.Pro.DQE.SqlServer.NET20.dll assembly.
public class ProfilingDynamicQueryEngine : DynamicQueryEngine
protected override DbCommand CreateCommand()
DbCommand cmd = base.CreateCommand();
ProfiledDbCommand pCmd = new ProfiledDbCommand(cmd, null, MiniProfiler.Current);
Here the DbCommand creation is overriden. Note that I wrap the original cmd and pass a current MiniProfiler instance as arguments to ProfiledDbCommand constructor, while I pass a null for the connection instance because it will be assigned later.
2. Derive from DataAccessAdapter class. Note: this class is generated from a template and you’ll find it in DBSpecificLayer project generated by LLBLGenPro.
public class DataAccessAdapterEx: DataAccessAdapter
protected override System.Data.Common.DbConnection CreateNewPhysicalConnection(string connectionString)
DbConnection conn = base.CreateNewPhysicalConnection(connectionString);
// return ProfiledDbConnection.Get(conn); Pre MvcMiniProfiler 1.9
return new ProfiledDbConnection(conn, MiniProfiler.Current);
protected override DynamicQueryEngineBase CreateDynamicQueryEngine()
return PostProcessNewDynamicQueryEngine(new ProfilingDynamicQueryEngine());
Within CreateDynamicQueryEngine I pass the class I’ve created in step #1. CreateNewPhysicalConnection will return a wrapped connection.
Instead of using DataAccessAdapter you should use the one created in step #2 - DataAccessAdapterEx. That’s it.
As it turns out, integrating MvcMiniProfiler with LLBLGenPro is quite easy. And the required coding might be added to LLBLGenPro templates by modifying them, so you won’t have to manually add the same code each time.
Let me know if you have feedback.
Update 19.9.2011: Updated the code because MvcMiniProiler introduced a breaking change in v1.9 (instead of ProfiledDbConnection.Get static method a constructor has to be used - thanks for swift response from David from LLBLGenPro support team)