实体框架和DbContext - 对象跟踪

时间:2011-08-17 20:35:19

标签: c# visual-studio-2010 entity-framework .net-4.0 entity-framework-4.1

我对实体框架中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();
}

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

3 个答案:

答案 0 :(得分:8)

这是正常的,并且在DbContext API固定行为的情况下,因为从一些非常奇怪的原因,DbSetDbQuery都没有公开MergeOption属性。对于ObjectContext API,您可以按MergeOptionObjectSet上公开的ObjectQuery设置行为。因此,如果您想刷新数据库中的值(并丢失更改),您可以执行以下操作:

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

如果您只想刷新交易,但又不想丢失更改,则可以使用MergeOption.PreserveChanges

答案 1 :(得分:2)

这取决于MergeOption查询的DefaultContext.Transactions。默认值AppendOnlywon't overwrite objects already in your context.您可以将其更改为OverwriteChanges以获得您期望的行为。

答案 2 :(得分:0)

与上述相关,当我遇到同样的错误时,这就是我降落的地方。但我想在我的情况下将合并选项设置为无跟踪。当我有一个试图关闭IQueryable的对象跟踪的excel导出方法时,我碰到了这个。通过我不会改变的大量数据,我不需要任何更改跟踪。

类似于下面的代码行在尝试将一些IQueryable转换为类ObjectQuery时会失败(但在其他类上成功。)

var y = ((ObjectQuery)query).MergeOption = MergeOption.NoTracking;

相反,我将其替换为使用 AsNoTracking

query = query.AsNoTracking();

回到最初的问题,这可能类似于下面的,在 System.Data.Entity

中添加的DBQuery上的Extention方法
List<Transactions> transactions = DefaultContext.Transactions.AsNoTracking().ToList();

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

相关问题