我对实体框架中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();
}
这是正常行为吗?我假设在我的初始查询中,它们被附加到对象上下文。然后,当我第二次查询时,它不会访问数据库,只是从对象上下文中提取实体,除非我清除/分离或单独重新加载所有实体。
答案 0 :(得分:8)
这是正常的,并且在DbContext API固定行为的情况下,因为从一些非常奇怪的原因,DbSet
或DbQuery
都没有公开MergeOption
属性。对于ObjectContext API,您可以按MergeOption
和ObjectSet
上公开的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
。默认值AppendOnly
,won'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