实体框架和DbContext -对象跟踪

本文关键字:对象 跟踪 DbContext 框架 实体 | 更新日期: 2023-09-27 18:06:00

我对DbContext在实体框架中的使用有点困惑。下面是我感到困惑的场景。

  • 我使用dbcontext的linq查询来获取数据。比如:

    List<Transactions> transactions = DefaultContext.Transactions.ToList();
    
  • 然后我直接在数据库中更新该查询返回的事务中的一个列。

  • 然后我再打电话:

    List<Transactions> transactions = DefaultContext.Transactions.ToList();
    

当列表这次返回时,它不反映我在运行update语句时所做的更新/更改,除非我循环遍历所有事务并重新加载它们:

foreach (DbEntityEntry<Transactions> item in DefaultContext.ChangeTracker.Entries<Transactions>())
{
    DefaultContext.Entry<Transactions>(item.Entity).Reload();
}

这是正常行为吗?我假设在我的初始查询中,它们被附加到对象上下文。然后,当我第二次查询时,它不会访问数据库,只是从对象上下文中取出实体,除非我清除/分离或单独重新加载所有实体。

实体框架和DbContext -对象跟踪

这是正常的,在DbContext API固定行为的情况下,因为从一些非常奇怪的原因,DbSetDbQuery都没有暴露MergeOption属性。在ObjectContext API的情况下,您可以设置MergeOption暴露在ObjectSetObjectQuery上的行为。因此,如果您想从数据库中刷新值(并丢失更改),您可以这样做:

ObjectContext objectContext = ((IObjectContextAdapter)dbContext).ObjectContext;
ObjectSet<Transactions> set = objectContext.CreateObjectSet<Transactions>();
set.MergeOption = MergeOption.OverwriteChanges;
List<Transactions> transactions = set.ToList();

如果你只是想刷新事务,但你不想失去你的更改,你可以使用MergeOption.PreserveChanges代替。

这取决于DefaultContext.Transactions查询的MergeOption。默认值AppendOnly不会覆盖上下文中已经存在的对象。您可以将其更改为OverwriteChanges以获得您期望的行为

与上述相关,当我遇到相同的错误时,这就是我着陆的地方。但我想在我的情况下设置合并选项不跟踪。当我有一个excel导出方法试图关闭IQueryable对象跟踪时,我遇到了这个问题。处理大量我不打算更改的数据,我不需要任何更改跟踪。

类似于下面的一行代码在尝试将一些IQueryables强制转换为ObjectQuery类时会失败(但对其他类则会成功)

var y = ((ObjectQuery)query).MergeOption = MergeOption.NoTracking;
相反,我用AsNoTracking 来代替它
query = query.AsNoTracking();
关于最初的问题,这可能像下面这样,在System.Data.Entity 中添加DBQuery上的extension方法
List<Transactions> transactions = DefaultContext.Transactions.AsNoTracking().ToList();

类似文章:https://msdn.microsoft.com/en-us/library/hh949853 (v = vs.113) . aspx