Я использую mvc-mini-profiler в своем проекте, созданном с помощью ASP. .Net MVC 3 и Entity Framework в первую очередь.
Все работает отлично, пока я не попытаюсь добавить профилирование базы данных, заключив соединение в ProfiledDbConnection
, как описано в документации. Поскольку я использую DbContext, я пытаюсь обеспечить соединение через конструктор с использованием статического фабричного метода:
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);
}
//...
}
При использовании ProfiledDbConnection
я получаю следующую ошибку:
ProviderIncompatibleException: The provider did not return a ProviderManifestToken string.
Трассировки стека:
[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
Я прошел, и тип, возвращаемый ProfiledDbConnection.Get
, имеет тип ProfiledDbConnection
(даже если текущий MiniProfiler имеет значение null).
Метод MiniProfiler.Start()
вызывается в методе Global Application_BeginRequest()
перед созданием экземпляра DbContext
. Я также вызываю метод Start для каждого запроса независимо от того, но вызываю stop, если пользователь находится в неправильной роли:
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();
}
Я не уверен, влияет ли это на вещи, но я также использую StructureMap как IoC для DbContext
, используя следующий инициализатор:
For<MyDbContext>().Singleton().HybridHttpOrThreadLocalScoped();
Я понимаю, что здесь есть аналогичный вопрос с хорошим объяснением того, что происходит для этого пользователя, однако, похоже, это не решает мою проблему.
ИЗМЕНИТЬ:
Для ясности. Я пытаюсь передать соединение как ProfiledDbConnection
, чтобы сначала профилировать сгенерированный sql из кода Entity Framework.
Entity Framework ожидает соединение с типом SqlConnection
, что, конечно же, не так.
Вот пример моей строки подключения (обратите внимание на providerName)
<add name="MyDbContext" connectionString="Server=.\SQLEXPRESS; Database=MyDatabase;Trusted_Connection=true;MultipleActiveResultSets=true" providerName="System.Data.SqlClient" />
Я попытался создать свою собственную версию ProfiledDbConnection
, унаследованную от SqlConnection
, но это закрытый класс.
Если есть какой-то способ сообщить Entity Framework о пользовательском типе подключения, возможно, это сработает. Я попытался установить providerName
в строке подключения на MvcMiniProfiler.Data.ProfiledDbConnection
, но это не сработало.
Так. Возможно, эволюция вопроса будет заключаться в следующем: как вы можете передать настраиваемый тип соединения в Entity Framework Code First?