Uso de perfiles de bases de datos mvc-mini-profiler con el código de Entity Framework primero

Estoy utilizando el mvc-mini-profiler en mi proyecto creado con ASP.Net MVC 3 y Entity Framework primero.

Todo funciona bien hasta que bash agregar perfiles de bases de datos al envolver la conexión en ProfiledDbConnection como se describe en la documentación. Dado que estoy usando un DbContext, la forma en que bash proporcionar la conexión es a través del constructor usando un método de fábrica estático:

 public class MyDbContext : DbContext { public MyDbContext() : base(GetProfilerConnection(), true) { } private static DbConnection GetProfilerConnection() { // Code below errors //return ProfiledDbConnection.Get(new SqlConnection(ConfigurationManager.ConnectionStrings["MyConnectionName"].ConnectionString)); // Code below works fine... return new SqlConnection(ConfigurationManager.ConnectionStrings["MyConnectionName"].ConnectionString); } //... } 

Cuando ProfiledDbConnection , ProfiledDbConnection el siguiente error:

ProviderIncompatibleException: The provider did not return a ProviderManifestToken string.

Stack Trace:

 [ArgumentException: The connection is not of type 'System.Data.SqlClient.SqlConnection'.] System.Data.SqlClient.SqlProviderUtilities.GetRequiredSqlConnection(DbConnection connection) +10486148 System.Data.SqlClient.SqlProviderServices.GetDbProviderManifestToken(DbConnection connection) +77 System.Data.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection) +44 [ProviderIncompatibleException: The provider did not return a ProviderManifestToken string.] System.Data.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection) +11092901 System.Data.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection) +11092745 System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection) +221 System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext) +61 System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input) +1203482 System.Data.Entity.Internal.LazyInternalContext.InitializeContext() +492 System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) +26 System.Data.Entity.Internal.Linq.InternalSet`1.Initialize() +89 System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext() +21 System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider() +44 System.Linq.Queryable.Where(IQueryable`1 source, Expression`1 predicate) +135 

He salido y el tipo devuelto por ProfiledDbConnection.Get es del tipo ProfiledDbConnection (incluso si el MiniProfiler actual es nulo).

El método MiniProfiler.Start() se llama dentro del método Global Application_BeginRequest() antes de que se DbContext una instancia de DbContext . También estoy llamando al método de inicio para cada solicitud independientemente de llamar a detener si el usuario no está en la función correcta:

  protected void Application_BeginRequest() { // We don't know who the user is at this stage so need to start for everyone MiniProfiler.Start(); } protected void Application_AuthorizeRequest(Object sender, EventArgs e) { // Now stop the profiler if the user is not a developer if (!AuthorisationHelper.IsDeveloper()) { MvcMiniProfiler.MiniProfiler.Stop(discardResults: true); } } protected void Application_EndRequest() { MiniProfiler.Stop(); } 

No estoy seguro si esto afecta las cosas, pero también estoy usando StructureMap como IoC para DbContext usando el siguiente inicializador:

 For().Singleton().HybridHttpOrThreadLocalScoped(); 

Entiendo que hay una pregunta similar aquí con una buena explicación de lo que está sucediendo para ese usuario, sin embargo, no parece resolver mi problema.

EDITAR:

Para mayor claridad. Estoy intentando pasar la conexión como ProfiledDbConnection para perfilar el sql generado desde el código del Entity Framework First.

Sql perfilado

Entity Framework espera una conexión con el tipo SqlConnection que por supuesto no es así.

Aquí hay un ejemplo de mi cadena de conexión (observe el providerName)

  

Intenté crear mi propia versión de ProfiledDbConnection heredando de SqlConnection pero es una clase sellada.

Si hay alguna forma de decirle a Entity Framework sobre el tipo de conexión personalizada, quizás esto funcione. Traté de establecer el providerName en la cadena de conexión a MvcMiniProfiler.Data.ProfiledDbConnection pero eso no funcionó.

Asi que. Tal vez una evolución de la pregunta sería: ¿cómo se puede pasar un tipo de conexión personalizada a Entity Framework Code First?

Esto ahora es totalmente compatible, mira la última fuente o toma el paquete de nuget.

Necesitará el paquete MiniProfiler.EF si está usando nuget. (1.9.1 y arriba)

Respaldar esto implicó un gran conjunto de modificaciones en el objeto proxy subyacente para permitir actuar como primeros proxies del código EF.

Para agregar este soporte:

Durante su ejecución de Application_Start :

MiniProfilerEF.Initialize();

Nota : EF Code First almacenará los metadatos de la tabla en una tabla llamada: EdmMetadata . Estos metadatos usan el proveedor como parte de la clave de entidad. Si inicializó su proveedor como proveedor no perfilado, tendrá que volver a generar estos metadatos. Eliminar todas las filas de EdmMetadata puede ser el truco, o bien, algunos proveedores más inteligentes pueden manejar esto de forma transparente.

Aún tenía problemas para hacer que esto funcionara y descubrí que necesitaba cambiar el nombre o eliminar la cadena de conexión para que Database.DefaultConnectionFactory funcione.

Por favor refiérase a esta respuesta para más detalles.

Este error en mi experiencia siempre ha sido una cadena de conexión no válida, o una falta de conexión a la base de datos, como “Se produjo un error de servicio de red al conectar …”.

También tenga en cuenta que el DbContext solo necesita el “connectionStringKey” en el constructor, como

 public MyDbContext() : base("MyConnectionName", true) { }