Я использую mvc-mini-profiler в моем проекте, построенном с использованием кода ASP.Net MVC 3 и Entity Framework.
Все работает отлично, пока я не попытаюсь добавить профилирование базы данных, завернув соединение в ProfiledDbConnection
, как описано в документации. Поскольку я использую DbContext, способ, которым я пытаюсь обеспечить соединение, - через конструктор, используя статический метод factory:
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()
вызывается в глобальном методе Application_BeginRequest()
до создания экземпляра DbContext
. Я также вызываю метод "Пуск" для каждого запроса независимо, но вызываю стоп, если пользователь не в правильной роли:
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();
Я понимаю, что здесь есть аналогичный вопрос с хорошим объяснением того, что происходит для этого пользователя, однако оно, похоже, не решает мою проблему.
EDIT:
Для ясности. Я пытаюсь передать соединение как ProfiledDbConnection
, чтобы профилировать сгенерированный sql из Entity Framework Code First.
В Entity Framework ожидается соединение с типом SqlConnection
, которое, конечно же, это не так.
Вот пример моей строки подключения (обратите внимание на имя поставщика)
<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?