使用mvc-mini-profiler数据库分析与Entity Framework Code First

时间:2011-07-01 15:35:35

标签: ef-code-first entity-framework-ctp5 mvc-mini-profiler

我在使用ASP.Net MVC 3和Entity Framework代码优先构建的项目中使用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为null)。

在实例化MiniProfiler.Start()之前,在全局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作为DbContext使用以下初始化程序的IoC:

For<MyDbContext>().Singleton().HybridHttpOrThreadLocalScoped();

我知道这里有一个类似的问题,对该用户的情况有一个很好的解释,但它似乎无法解决我的问题。

修改

为清楚起见。我试图将连接作为ProfiledDbConnection传递,以便从Entity Framework Code First中分析生成的sql。

Profiled Sql

实体框架期望与类型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,但这不起作用。

因此。也许问题的演变是:如何将自定义连接类型传递给实体框架代码优先?

3 个答案:

答案 0 :(得分:13)

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

如果您使用的是nuget,则需要MiniProfiler.EF包。 (1.9.1及以上)

支持这一点涉及对底层代理对象的大量修改,以支持充当EF代码优先代理。

添加此支持:

Application_Start运行期间

MiniProfilerEF.Initialize();

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

答案 1 :(得分:2)

我仍然遇到问题,我发现需要重命名或删除连接字符串以使Database.DefaultConnectionFactory正常工作。

Please refer to this answer for more detail.

答案 2 :(得分:-1)

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

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

public MyDbContext() : 
     base("MyConnectionName", true)
    { }
相关问题