Я установил mvc-mini-profiler для моего сайта MVC 3 на базе Entity Framework. Все настроено должным образом; Запуск профилирования в Application_Start, завершение в Application_End и так далее. Часть профилирования работает нормально.
Однако, когда я пытаюсь поменять местами создание объекта модели данных на предоставление профилируемых версий, производительность резко падает. Не каждый SQL-запрос, но некоторые запросы занимают примерно 5-кратную загрузку всей страницы. (Самая первая загрузка страницы после запуска IIS Express занимает немного больше времени, но это продолжается.)
Незначительное время (максимум ~ 2 мс) тратится на запросы, выполнение и "чтение данных" SQL, в то время как эта строка:
var person = dataContext.People.FirstOrDefault(p => p.PersonID == id);
... при заключении в с использованием (profiler.Step ())
записывается как занимающая 300-400 мс. Я профилировал с помощью dotTrace, который подтвердил, что время на самом деле тратится в EF как обычно (профилируемые компоненты появляются очень кратко), только это занимает гораздо больше времени.
Это заставляет меня полагать, что соединение или его часть в составных частях отсутствует достаточное количество данных, из-за чего EF работает намного хуже.
Это то, что я использую для создания объекта контекста (класс моей модели edmx называется DataContext):
var conn = ProfiledDbConnection.Get(
/* returns an SqlConnection */CreateConnection());
return CreateObjectContext(conn);
Изначально я использовал mvc-mini-profiler предоставлен метод ObjectContextUtils.CreateObjectContext
. Я погрузился в него и заметил, что он устанавливает строку пути к рабочей области метаданных с подстановочными знаками. Поскольку у меня уровень базы данных изолирован для одного проекта и нескольких сайтов MVC, как и для других проектов, использующих код, эти пути изменились, и я бы предпочел быть более конкретным. Кроме того, я думал, что это причина проблемы с производительностью. Я продублировал функциональность CreateObjectContext
в моем собственном проекте, чтобы обеспечить это как таковое:
public static T CreateObjectContext(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.Ctor(ec);
}
... но, похоже, это не имеет большого значения. Проблема все еще существует, использую ли я вышеупомянутую взломанную версию, более конкретную с путями рабочих областей метаданных, или версию, предоставленную mvc-mini-profiler. Я просто подумал, что упомяну, что я тоже пробовал это.
Исчерпав все это, я нахожусь в упадке. Еще раз: когда я просто предоставляю свой контекст данных как обычно, производительность не теряется. Когда я предоставляю «профилируемый» контекст данных, производительность для определенных запросов падает (я тоже не знаю, что на это влияет). Что может сделать mvc-mini-profiler неправильно? Я по-прежнему скармливаю ему неправильные данные?
Думаю, это та же проблема, с которой столкнулся этот человек .