我已经针对我的实体框架驱动的 MVC 3 站点设置了 mvc-mini-profiler。一切都已适当配置;在 Application_Start 中开始分析,在 Application_End 中结束,依此类推。分析部分工作得很好。
但是,当我尝试将我的数据模型对象生成交换为提供可分析的版本时,性能会变慢。不是每个 SQL 查询,但有些查询大约需要整个页面加载的 5 倍。(启动 IIS Express 后的第一个页面加载需要更长的时间,但这是持续的。)
查询、执行和“读取数据”SQL 所花费的时间可以忽略不计(大约 2 毫秒),而这一行:
var person = dataContext.People.FirstOrDefault(p => p.PersonID == id);
...当包裹在using(profiler.Step())
被记录为需要 300-400 毫秒。我使用 dotTrace 进行了分析,这证实了时间实际上像往常一样在 EF 中花费(可分析的组件确实出现非常短暂),只是花费的时间要长得多。
这使我相信连接或其某些组成部分缺少足够的数据,从而使 EF 的性能更差。
这就是我用来制作上下文对象的内容(我的 edmx 模型的类称为 DataContext):
var conn = ProfiledDbConnection.Get(
/* returns an SqlConnection */CreateConnection());
return CreateObjectContext<DataContext>(conn);
我最初使用 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 a duplicate CtorCache too to make this work.
var factory = DbProviderServices.GetProviderFactory(connection);
var itemCollection = workspace.GetItemCollection(System.Data.Metadata.Edm.DataSpace.SSpace);
itemCollection.GetType().GetField("_providerFactory", // <==== big fat ugly hack
BindingFlags.NonPublic | BindingFlags.Instance).SetValue(itemCollection, factory);
var ec = new System.Data.EntityClient.EntityConnection(workspace, connection);
return CtorCache<T, System.Data.EntityClient.EntityConnection>.Ctor(ec);
}
......但它似乎并没有太大的区别。无论我使用上述更具体的元数据工作区路径还是 mvc-mini-profiler 提供的版本,问题仍然存在。我只是想我会提到我也试过这个。
用尽了这一切,我已经束手无策了。再一次:当我像往常一样提供我的数据上下文时,没有性能损失。当我提供“可分析的”数据上下文时,某些查询的性能会下降(我也不知道是什么影响了这一点)。mvc-mini-profiler 做错了什么?我还在给它输入错误的数据吗?
我认为这与此人遇到的问题相同。