Friday, June 17, 2011

MiniProfiler with PetaPoco

Integrating PetaPoco with Mvc Mini Profiler can be done by changing a few lines in PetaPoco.cs to wrap the connection with a MvcMiniProfiler.Data.ProfiledDbConnection and by changing a line that gets a command using the factory to use the connection. I've written a simple DbProviderFactory that acts as a proxy to the SQL Server factory so you don't have to make any changes to PetaPoco. You register it by adding a system.data element under the root configuration element in your web.config to register the factory and change your connect strings to use the new provider:

<configuration>
  <system.data>
    <DbProviderFactories>
      <add name="MiniProfiler Data Provider"
           invariant="MiniProfilerSql"
           description="SqlServer wrapper for MiniProfiler"
           type="WebSupport.Code.MiniProfilerSqlProviderFactory, WebSupport"
      />
    </DbProviderFactories>
  </system.data>
  <connectionStrings>
    <add name="Test" providerName="MiniProfilerSql" connectionString="xxxx" />
  </connectionStrings>

Notice in the type attribute that my class is in the WebSupport.Code namespace, the value after the comma shows that it is in the WebSupport assembly I have referenced in my MVC project. If you want to stop using MiniProfiler you can just change your connect strings back to using System.Data.SqlClient as the provider.

Here's the code, you should be able to change it for other providers by changing the provider name in the constructor:

public class MiniProfilerSqlProviderFactory : DbProviderFactory
    {
        public static MiniProfilerSqlProviderFactory Instance = new MiniProfilerSqlProviderFactory();

        DbProviderFactory _factory;

        public override bool CanCreateDataSourceEnumerator
        {
            get
            {
                return _factory.CanCreateDataSourceEnumerator;
            }
        }

        public override DbCommand CreateCommand()
        {
            return _factory.CreateCommand();
        }

        public override DbCommandBuilder CreateCommandBuilder()
        {
            return _factory.CreateCommandBuilder();
        }

        public override DbConnection CreateConnection()
        {
            DbConnection cnn = _factory.CreateConnection();
            return MvcMiniProfiler.Data.ProfiledDbConnection.Get(cnn);
        }

        public override DbConnectionStringBuilder CreateConnectionStringBuilder()
        {
            return _factory.CreateConnectionStringBuilder();
        }

        public override DbDataAdapter CreateDataAdapter()
        {
            return _factory.CreateDataAdapter();
        }

        public override DbDataSourceEnumerator CreateDataSourceEnumerator()
        {
            return _factory.CreateDataSourceEnumerator();
        }

        public override DbParameter CreateParameter()
        {
            return _factory.CreateParameter();
        }

        public override CodeAccessPermission CreatePermission(PermissionState state)
        {
            return _factory.CreatePermission(state);
        }

        public MiniProfilerSqlProviderFactory()
        {
            _factory = DbProviderFactories.GetFactory("System.Data.SqlClient");
        }
    }