ef code first - Uso de perfiles de bases de datos mvc-mini-profiler con el código de Entity Framework primero
ef-code-first entity-framework-ctp5 (3)
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.
Estoy utilizando el mvc-mini-profiler en mi proyecto creado con ASP.Net MVC 3 y Entity Framework primero.
Todo funciona bien hasta que intento 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 intento 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<MyDbContext>().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.
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)
<add name="MyDbContext" connectionString="Server=./SQLEXPRESS; Database=MyDatabase;Trusted_Connection=true;MultipleActiveResultSets=true" providerName="System.Data.SqlClient" />
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?
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)
{ }
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.