EntityFramework Core不返回新数据

时间:2018-07-12 22:41:57

标签: c# .net entity-framework-core

使用EntityFramework Core,我有以下代码:

task2

两个断言均失败。似乎在第二次调用中,div仍返回旧的var theStudent = new Student(); theStudent.Title = "Mehran" theStudent.Status = 1 mainDbContext.Set<Student>().Add(theStudent); await mainDbContext.SaveChangesAsync(); // In reality data is changed by another program. To simulate it here I alter the data by another dbcontext and raw SQL using (var utilDbContext = new MelkRadarDbContext()) { var command = " update dbo.Student set status=2 where Id=@p0"; utilDbContext.Database.ExecuteSqlCommand(command, theStudent.Id); } var reloadedStudent = await mainDbContext.Set<Student>() .Where(s => s.Id == theStudent.Id) .FirstOrDefaultAsync(); Assert.AreNotEqual(reloadedStudent, student); Assert.AreEqual(reloadedStudent.Status, 2); 对象为mainDbContext,并且没有从数据库中加载它来获取最新数据。为什么呢?我应该怎么做才能在数据库上获取最新数据?

2 个答案:

答案 0 :(得分:2)

简短答案:

您有两个选择:

  1. [不推荐]对每个实体使用ReloadReloadAsync方法:

    await mainDbContext.Entry(theStudent).ReloadAsync();
    

    由于必须分别为每个实体调用此方法,因此当您需要重新加载一堆实体时,效率非常低。

  2. [推荐]创建一个新的DbContext。这是解决陈旧数据问题的最终方法。

详情:

DbContext被设计为短命的。它们实现了Unit Of Work模式,因此建议为每一批相关操作(业务交易)都创建一个DbContext-例如,用户操作(按“保存”按钮)。尽管对于每个HTTP请求(在Web应用程序或Web服务的上下文中)只有一个DbContext的通用做法可以满足此要求,但是有时您需要在一个请求中执行多个“操作批处理”。那是您需要考虑创建更多DbContext的时候了。

为一系列操作保留一个DbContext的全部要点是缓存跟踪延迟加载 。每当您需要重新加载数据时,很明显,您从此位置都不需要这些功能。因此,使用新的DbContext很有意义。

一个很好的答案是,为什么首先需要新数据?如果您需要根据数据做出关键决策,并且依赖过时的数据会导致数据存储不一致,那么即使刷新实体也无济于事。在这种情况下,您需要使用更强大的机制,例如锁(数据库或其他方式)来防止陈旧数据。

注意:在 Entity Framework 6 中,有一种Refresh方法可用于立即刷新所有对象。该方法在 Entity Framework Core 中不可用,因为它并没有被证明有用。

答案 1 :(得分:0)

DbContext为要求从数据存储中检索的对象提供了一级缓存。随后对同一对象的请求将返回缓存的对象,而不是执行另一个数据库请求。

该对象已在主上下文中缓存,并且尚未更新,因为在更新对象时使用了不同的上下文,因此可以在加载之前使用AsNoTracking忽略缓存,但对于您而言,对象已初始化,然后附加到上下文(已缓存),您可以执行的操作是分离EntityState对象,以便上下文不再跟踪该对象,然后可以再次加载它,希望对您有用。

   mainDbContext.Entry(theStudent).State = EntityState.Detached;
    var reloadedStudent = await mainDbContext.Set<Student>()
        .Where(s => s.Id == theStudent.Id)
        .FirstOrDefaultAsync();