goa*_*960 9 c# enterprise-library mvc-mini-profiler
我确信可以分析Enterprise Library SQL命令,但我无法弄清楚如何包装连接.这就是我想出的:
Database db = DatabaseFactory.CreateDatabase();
DbCommand dbCommand = db.GetStoredProcCommand(PROC);
ProfiledDbCommand cmd = new ProfiledDbCommand(dbCommand, dbCommand.Connection, MvcMiniProfiler.MiniProfiler.Current);
db.AddInParameter(cmd, "foo", DbType.Int64, 0);
DataSet ds = db.ExecuteDataSet(cmd);
Run Code Online (Sandbox Code Playgroud)
这导致以下异常:
无法将类型为"MvcMiniProfiler.Data.ProfiledDbCommand"的对象强制转换为"System.Data.SqlClient.SqlCommand".
Jon*_*nas 12
例外来自Entlib Database.DoLoadDataSet中的这一行
((IDbDataAdapter) adapter).SelectCommand = command;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,适配器的类型为SqlDataAdapter,它需要一个SqlCommand,ProfiledDbProviderFactory创建的命令的类型为ProfiledDbCommand,如异常所示.
此解决方案将通过覆盖ProfiledDbProviderFactory中的CreateDataAdapter和CreateCommand为EntLib提供通用DbDataAdapter.它似乎可行,但如果我监督了这个黑客可能造成的任何不必要的后果(或者它可能造成的眼睛疼痛),我道歉.在这里:
创建两个新类ProfiledDbProviderFactoryForEntLib和DbDataAdapterForEntLib
public class ProfiledDbProviderFactoryForEntLib : ProfiledDbProviderFactory
{
private DbProviderFactory _tail;
public static ProfiledDbProviderFactory Instance = new ProfiledDbProviderFactoryForEntLib();
public ProfiledDbProviderFactoryForEntLib(): base(null, null)
{
}
public void InitProfiledDbProviderFactory(IDbProfiler profiler, DbProviderFactory tail)
{
base.InitProfiledDbProviderFactory(profiler, tail);
_tail = tail;
}
public override DbDataAdapter CreateDataAdapter()
{
return new DbDataAdapterForEntLib(base.CreateDataAdapter());
}
public override DbCommand CreateCommand()
{
return _tail.CreateCommand();
}
}
public class DbDataAdapterForEntLib : DbDataAdapter
{
private DbDataAdapter _dbDataAdapter;
public DbDataAdapterForEntLib(DbDataAdapter adapter)
: base(adapter)
{
_dbDataAdapter = adapter;
}
}
Run Code Online (Sandbox Code Playgroud)在Web.config中,将ProfiledDbProviderFactoryForEntLib添加到DbProviderFactories并将ProfiledDbProviderFactoryForEntLib设置为您的connectionstring的providerName
<configuration>
<configSections>
<section name="dataConfiguration" type="..." />
</configSections>
<connectionStrings>
<add name="SqlServerConnectionString" connectionString="Data Source=xyz;Initial Catalog=dbname;User ID=u;Password=p"
providerName="ProfiledDbProviderFactoryForEntLib" />
</connectionStrings>
<system.data>
<DbProviderFactories>
<add name="EntLib DB Provider"
invariant="ProfiledDbProviderFactoryForEntLib"
description="Profiled DB provider for EntLib"
type="MvcApplicationEntlib.ProfiledDbProviderFactoryForEntLib, MvcApplicationEntlib, Version=1.0.0.0, Culture=neutral"/>
</DbProviderFactories>
</system.data>
<dataConfiguration defaultDatabase="..." />
<appSettings>... <system.web>... etc ...
</configuration>
Run Code Online (Sandbox Code Playgroud)
(MvcApplicationEntlib是我的测试项目的名称)
在对DB进行任何调用之前设置ProfiledDbProviderFactoryForEntLib(对黑客敏感的读者会被警告,这就是丑陋的地方)
//In Global.asax.cs
protected void Application_Start()
{
ProfiledDbProviderFactoryForEntLib profiledProfiledDbProviderFactoryFor = ((ProfiledDbProviderFactoryForEntLib)DbProviderFactories.GetFactory("ProfiledDbProviderFactoryForEntLib"));
DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.SqlClient"); //or whatever predefined factory you want to profile
profiledProfiledDbProviderFactoryFor.InitProfiledDbProviderFactory(MiniProfiler.Current, factory);
...
Run Code Online (Sandbox Code Playgroud)
这可能是以更好的方式或在其他地方完成的.MiniProfiler.Current在这里将为null,因为此处没有任何内容.
像从头开始一样调用存储过程
public class HomeController : Controller
{
public ActionResult Index()
{
Database db = DatabaseFactory.CreateDatabase();
DbCommand dbCommand = db.GetStoredProcCommand("spGetSomething");
DbCommand cmd = new ProfiledDbCommand(dbCommand, dbCommand.Connection, MiniProfiler.Current);
DataSet ds = db.ExecuteDataSet(cmd);
...
Run Code Online (Sandbox Code Playgroud)编辑:好的不确定你想如何使用它.跳过手动创建ProfiledDbCommand.需要使用miniprofiler为每个请求启动ProfiledDbProviderFactory.
在Global.asax.cs中,删除对Application_Start所做的更改(上面步骤3中的出厂设置),将其添加到Application_BeginRequest中.
ProfiledDbProviderFactoryForEntLib profiledProfiledDbProviderFactoryFor = ((ProfiledDbProviderFactoryForEntLib) DbProviderFactories.GetFactory("ProfiledDbProviderFactoryForEntLib"));
DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.SqlClient");
profiledProfiledDbProviderFactoryFor.InitProfiledDbProviderFactory(MvcMiniProfiler.MiniProfiler.Start(), factory);
Run Code Online (Sandbox Code Playgroud)从ProfiledDbProviderFactoryForEntLib中删除方法CreateCommand,让ProfiledDbProviderFactory创建profiled命令.
执行您的SP而不创建ProfiledDbCommand,就像这样
Database db = DatabaseFactory.CreateDatabase();
DbCommand dbCommand = db.GetStoredProcCommand("spGetSomething");
DataSet ds = db.ExecuteDataSet(dbCommand);
Run Code Online (Sandbox Code Playgroud)