24

我在使用 ASP.Net MVC 3 和实体框架代码优先构建的项目中使用mvc-mini-profiler

一切都很好,直到我尝试通过将连接包装在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 为空)。

在实例化之前,该方法MiniProfiler.Start()在 Global 方法中被调用。我也为每个请求调用 Start 方法,但如果用户不是正确的角色,则调用 stop :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();

我知道这里有一个类似的问题,很好地解释了该用户正在发生的事情,但它似乎并没有解决我的问题。

编辑:

为了清楚起见。我正在尝试传递连接ProfiledDbConnection,以便从 Entity Framework Code First 分析生成的 sql。

分析的 Sql

实体框架期待与类型的连接,SqlConnection这当然不是。

这是我的连接字符串的示例(请注意 providerName)

<add name="MyDbContext" connectionString="Server=.\SQLEXPRESS; Database=MyDatabase;Trusted_Connection=true;MultipleActiveResultSets=true" providerName="System.Data.SqlClient" />

我试图创建我自己的ProfiledDbConnection继承版本,SqlConnection但它是一个密封类。

如果有某种方式可以告诉实体框架有关自定义连接类型的信息,那么这可能会起作用。我尝试将providerName连接字符串中的设置为,MvcMiniProfiler.Data.ProfiledDbConnection但没有奏效。

所以。问题的演变可能是:如何将自定义连接类型传递给 Entity Framework Code First?

4

3 回答 3

13

现在完全支持,请查看最新源或从 nuget 获取包。

如果您使用 nuget,您将需要 MiniProfiler.EF 包。(1.9.1 及更高版本)

支持这一点需要对底层代理对象进行大量修改,以支持充当 EF 代码优先代理。

要添加此支持:

在你的Application_Start跑步过程中:

MiniProfilerEF.Initialize();

注意:EF Code First 会将表元数据存储在名为: 的表中EdmMetadata。此元数据使用提供者作为实体键的一部分。如果您将您的提供程序初始化为未配置文件的提供程序,您将不得不重新构建此元数据。删除所有行EdmMetadata可能会起作用,或者一些更聪明的提供者能够透明地处理这个问题。

于 2011-07-19T07:56:46.393 回答
2

我仍然无法让它工作,并发现我需要重命名或删除连接字符串才能让 Database.DefaultConnectionFactory 工作。

有关更多详细信息,请参阅此答案。

于 2011-07-23T13:53:50.260 回答
-1

根据我的经验,这个错误一直是无效的连接字符串,或者缺少与数据库的连接,例如“连接时发生网络服务错误......”。

另请注意,DbContext 只需要构造函数中的“connectionStringKey”,例如

public MyDbContext() : 
     base("MyConnectionName", true)
    { }
于 2011-07-12T21:02:31.267 回答