Причины того, что аналогичные запросы будут иметь улучшенное время отклика, разнообразны.
- Большинство систем управления базами данных кэшируют части извлеченных данных, поэтому подобные запросы в ближайшем будущем будут выполняться быстрее.Если вы выполните запрос
Teachers with their Students
, то таблица Teachers
будет объединена с таблицей Students
.Этот результат соединения довольно часто кешируется некоторое время.Следующий запрос для Teachers with their Students
будет повторно использовать этот результат объединения и, следовательно, станет быстрее DbContext
кэширует запрашиваемый объект.Если вы выберете учителя Single
или Find
, он будет сохранен в локальной памяти.Это должно быть в состоянии определить, какие элементы изменены, когда вы звоните SaveChanges
.Если вы Find
снова наберете Teacher
, этот запрос будет быстрее.Я не уверен, произойдет ли то же самое, если вы запросите 1000 Teachers
. - Когда вы создаете объект
DbContext
, инициализатор проверяется, чтобы увидеть, была ли модель изменена или нет.
Так что может показаться неуместным Dispose()
созданного DbContext
, но вы видите, что большинство людей поддерживают DbContext
в течение довольно короткого времени:
using (var dbContext = new MyDbContext(...))
{
var fetchedTeacher = dbContext.Teachers
.Where(teacher => teacher.Id = ...)
.Select(teacher => new
{
Id = teacher.Id,
Name = teacher.Name,
Students = teacher.Students.ToList(),
})
.FirstOrDefault();
return fetchedTeacher;
}
// DbContext is Disposed()
ВНа первый взгляд может показаться, что было бы лучше сохранить DbContext
живым.Если кто-то запрашивает тот же Teacher
, DbContext
не нужно будет запрашивать его у базы данных, он может вернуть локального Учителя ..
Однако сохранение DbContext
в живых может привести к тому, чтовы получаете неверные данные.Если кто-то еще изменит Teacher
между вашим первым и вторым запросом для этого Teacher
, вы получите старые Teacher
данные.
Следовательно, разумно сохранить время жизни DbContext
как можно короче.
Что я могу сделать, чтобы улучшить скорость первого запроса?
Да, вы можете!
Первое, что вы можете сделать, это установить инициализацию вашей базы данных так, чтобы она не проверяла существование и модель базы данных.Конечно, вы можете сделать это только тогда, когда уверены, что ваша база данных существует и не изменилась.
// constructor; disables initializer
public SchoolDBContext() : base(...)
{
//Disable initializer
Database.SetInitializer<SchoolDBContext>(null);
}
Другое дело, если вы уже выбрали объект для обновления базы данных, и выВы уверены, что никто не изменил объект, вы можете Attach
его, вместо того, чтобы извлекать его снова, , как показано в этом вопросе
Нормальное использование:
// update the name of the teacher with teacherId
void ChangeTeacherName(int teacherId, string name)
{
using (var dbContext = new SchoolContext(...))
{
// fetch the teacher, change the name and save
Teacher fetchedTeacher = dbContext.Teachers.Find(teacherId);
fetchedTeader.Name = name;
dbContext.SaveChanges();
}
}
Использование Attach
для обновления ранее загруженного Учителя:
void ChangeTeacherName (Teacher teacher, string name)
{
using (var dbContext = new SchoolContext(...))
{
dbContext.Teachers.Attach(teacher);
dbContext.Entry(teacher).Property(t => t.Name).IsModified = true;
dbContext.SaveChanges();
}
}
Использование этого метода не требует повторной загрузки Учителя.Во время SaveChanges проверяется значение IsModified
всех свойств всех Attached
элементов.При необходимости они будут обновлены.