首先使用实体框架代码使用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
返回的types是ProfiledDbConnection.Get
types(即使当前的MiniProfiler为null)。
在实例化DbContext
之前,在Global Application_BeginRequest()
方法中DbContext
Application_BeginRequest()
方法。 我也为每个请求调用Start方法,不pipe如何调用stop,如果用户不是正确的angular色:
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代码优先生成生成的sql。
entity framework期望与SqlConnection
types的连接,当然这不是。
这是我的连接string的一个例子(注意providerName)
<add name="MyDbContext" connectionString="Server=.\SQLEXPRESS; Database=MyDatabase;Trusted_Connection=true;MultipleActiveResultSets=true" providerName="System.Data.SqlClient" />
我试图创build我自己的从SqlConnection
inheritance的ProfiledDbConnection
的版本,但它是一个密封的类。
如果有某种方式告诉entity framework关于自定义连接types,那么也许这将工作。 我尝试将连接string中的providerName
设置为MvcMiniProfiler.Data.ProfiledDbConnection
但没有奏效。
所以。 也许这个问题的演变将是:你如何将自定义连接types传递给entity framework代码优先?
现在完全支持,请查看最新的源代码或从nuget获取软件包。
如果您正在使用nuget,您将需要MiniProfiler.EF软件包。 (1.9.1及以上)
支持这项工作需要对底层代理对象进行大量的修改,以支持充当EF代码的第一代理。
要添加这个支持:
在Application_Start
运行期间:
MiniProfilerEF.Initialize();
注意 :EF Code First会将表元数据存储在名为EdmMetadata
的表中。 这个元数据使用提供者作为实体键的一部分。 如果您将提供程序初始化为非简介提供程序,则必须重新构build此元数据。 从EdmMetadata
删除所有的行可能会诀窍,或者一些聪明的提供者能够透明地处理。
我仍然有问题得到这个工作,发现我需要重命名或删除连接string来获取Database.DefaultConnectionFactory工作。
有关更多详细信息,请参阅此答案。
在我的经验中,这个错误一直是一个无效的连接string,或缺乏连接到数据库,如“连接中发生networking服务错误…”。
还要注意,DbContext只需要构造函数中的“connectionStringKey”就好
public MyDbContext() : base("MyConnectionName", true) { }