繁体   English   中英

实体框架中DbContext的奇怪行为

[英]Strange Behavior of DbContext in Entity Framework

它是这样的:

MyDbContext ctx = new MyDbContext();

IFooRepository repo = new FooRepository(ctx);
var items = repo.GetAvailableItem().ToList(); //this will query all item.sold = false.

// here it returns three rows
foreach(var item in items) {
    item.sold = true;
}

repo.commit();     // this will call the SaveChanges() in DbContext

Thread.sleep(10000) 

// Now I quickly execute a query in SQL Server Management Studio 
// UPDATE Item SET Sold = 0;
var items02 = repo.GetAvailableItem().ToList();   // this will query all item.sold = false.

// here items02 also contains three rows
// HOWEVER, when I watch the value of item.sold in items02, it is all True

这是设计使然吗?

为什么? 是否因为DbContext缓存了实体并且即使再次运行相同的查询也从不刷新?


更新

这是我的仓库中的代码:

public IQueryable<Item> GetAvailableItem()
{
    var items = from x in DbContext.Item
                        where x.Sold == 0
                        select x;
    return items;
}

public virtual int Commit()
{
    return DbContext.SaveChanges();
}

好。 这是发生了什么:

  1. 创建一个新的上下文。
  2. 通过调用GetAvailableItem()从数据库加载项目
  3. 上下文将加载它们并缓存它们。
  4. 通过上下文更新项目。 因此:db行已更新,并且缓存版本也已更新。
  5. 在上下文外部(通过SSMS)通过纯sql更新项目。 因此:数据库行已更新。 但是,由于您使用的上下文与以前相同,并且它具有项目的自身版本,因此无法知道自身外部发生的情况,因此,项目的缓存版本将保持原样:不会更新。

如果您想让上下文知道自身外部的变化,最简单的方法是创建一个新的上下文并再次查询。 另一种方法是通过yourContext.Entry<YourEntityType>(entityInstance).Reload();告诉上下文明确地从db重新加载实体yourContext.Entry<YourEntityType>(entityInstance).Reload();

我的猜测是您的DbContext尚未与数据库中发生的更改保持最新(您说过您正在Thread.sleep中运行更新)。 DbContext将不会接收这些更新(数据已缓存)。

这就是为什么您希望对上下文的生命周期尽可能短以减少并发性。 这是预期的行为。

看到这个MSDN帖子

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM