为了从EF 4.1获得单个回调,我可以编写的最小代码量是多少,它提供了以下内容:
OnSQLExecuted(DbCommand cmd, DateTime start, double durationMS, string stacktrace) 目前我们使用了一个似乎在泄露性能的令人讨厌的黑客,我很好奇我们如何能够以最小的影响对应用程序实现此回调.
我们能够通过黑客入侵Mini Minir来解决这个问题 - Database.DefaultConnectionFactory但是我们改变了默认工厂的默认情况意味着你不能同时拥有两个分析工厂.所以我们采取了更激进的路线.
常用的技术是相当直接的,你实现:DbProviderFactory,IDbConnectionFactory,DbProviderServices,DbConnection,DbCommand并DbDataReader以这样的方式,他们拦截电话和个人资料.
到目前为止,很容易......但是当你试图连接它时它会变得混乱:
try
{
// ensure all the factories are loaded
DbProviderFactories.GetFactory("...");
}
catch (ArgumentException)
{
}
Type type = typeof(DbProviderFactories);
DataTable table;
// SUPER UGLY - Can this be done in another way?
object setOrTable = (type.GetField("_configTable", BindingFlags.NonPublic | BindingFlags.Static) ??
type.GetField("_providerTable", BindingFlags.NonPublic | BindingFlags.Static)).GetValue(null);
if (setOrTable …Run Code Online (Sandbox Code Playgroud) 我已经针对我的Entity Framework支持的MVC 3站点设置了mvc-mini-profiler.一切都是适当的配置; 在Application_Start中开始分析,在Application_End中结束它,依此类推.分析部分工作得很好.
但是,当我尝试将我的数据模型对象生成交换为提供可分发的版本时,性能会变慢.不是每个SQL查询,但有些查询占用整个页面加载量的大约5倍.(启动IIS Express后第一页加载需要更长时间,但这是持续的.)
可忽略不计的时间(~2ms tops)用于查询,执行和"数据读取"SQL,而这一行:
var person = dataContext.People.FirstOrDefault(p => p.PersonID == id);
Run Code Online (Sandbox Code Playgroud)
...当被包裹时using(profiler.Step())记录为300-400毫秒.我用dotTrace进行了分析,确认时间实际上是照常用于EF(可用的组件确实非常短暂地出现),只是需要更长的时间.
这使我相信连接或其某些组成部分缺少足够的数据,使EF表现更差.
这就是我用来制作上下文对象的东西(我的edmx模型的类叫做DataContext):
var conn = ProfiledDbConnection.Get(
/* returns an SqlConnection */CreateConnection());
return CreateObjectContext<DataContext>(conn);
Run Code Online (Sandbox Code Playgroud)
我最初使用的是mvc-mini-profiler提供的ObjectContextUtils.CreateObjectContext方法.我深入研究它并注意到它设置了一个通配符元数据工作空间路径字符串.由于我将数据库层隔离到一个项目,而将几个MVC站点作为使用代码的其他项目隔离,因此这些路径已经改变,我宁愿更具体.另外,我认为这是性能问题的原因.我将CreateObjectContext功能复制到我自己的项目中以提供此功能,如下所示:
public static T CreateObjectContext<T>(DbConnection connection) where T : System.Data.Objects.ObjectContext {
var workspace = new System.Data.Metadata.Edm.MetadataWorkspace(
GetMetadataPathsString().Split('|'),
// ^-- returns
// "res://*/Redacted.csdl|res://*/Redacted.ssdl|res://*/Redacted.msl"
new Assembly[] { typeof(T).Assembly });
// The remainder of the method is copied straight from the original,
// and I carried over …Run Code Online (Sandbox Code Playgroud) 我们安装了miniprofiler.它一直是一种启发性的体验,但是现在我们看到我们的数据库查询运行速度提高了3倍,启用了启动器,因为它已禁用.
我们在应用程序中更改的唯一代码是添加profiledDbConnection:
public static DbConnection GetOpenConnection(string connectionString)
{
var cnn = new System.Data.SqlClient.SqlConnection(connectionString);
// wrap the connection with a profiling connection that tracks timings
return MvcMiniProfiler.Data.ProfiledDbConnection.Get(cnn, MiniProfiler.Current);
}
Run Code Online (Sandbox Code Playgroud)
Linq2Sql突然......快.
我不是在抱怨,但为什么会这样呢?