是否可以延长 EF6 预热时间?



我有一个应用程序,我在其中验证以下行为:长时间不活动后的第一个请求需要很长时间,有时会超时。 是否可以控制实体框架管理对象释放的方式?是否可以将某些实体标记为永远不会被处置? ...为了避免/改善预热时间?

问候

类似查询将具有改进的响应时间的原因是多方面的。

  • 大多数数据库管理系统会缓存部分获取的数据,因此在不久的将来类似的查询会更快。如果执行Teachers with their Students查询,则Teachers表将与Students表联接。此联接结果通常会缓存一段时间。Teachers with their Students的下一个查询将重用此联接结果,从而变得更快
  • DbContext缓存查询的对象。如果选择Single教师或Find教师,则会将其保留在本地内存中。这是为了能够在调用SaveChanges时检测哪些项目发生了更改。如果再次Find相同的Teacher,则此查询将更快。我不确定如果您查询 1000Teachers,是否会发生同样的情况.
  • 创建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活着会更好。如果有人要求相同的TeacherDbContext就不必向数据库请求它,它可以返回本地教师。

但是,保持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();
}
}

使用此方法不需要再次获取教师。在保存更改期间,将检查所有Attached项的所有属性的IsModified值。如果需要,它们将被更新。

最新更新