entity framework和DbContext – 对象跟踪
我对Entity Framework中DbContext的使用有点困惑。 这是我很困惑的场景。
-
我使用dbcontext中的linq查询来获取数据。 就像是:
List transactions = DefaultContext.Transactions.ToList();
-
然后我直接在数据库中更新该查询中返回的一个事务中的列。
-
然后我再打电话:
List transactions = DefaultContext.Transactions.ToList();
当列表返回这次时,它不会反映我在运行update语句时所做的更新/更改,除非我遍历所有事务并重新加载它们:
foreach (DbEntityEntry item in DefaultContext.ChangeTracker.Entries()) { DefaultContext.Entry(item.Entity).Reload(); }
这是正常的行为吗? 我假设在我的初始查询中,它们被附加到对象上下文。 然后当我第二次查询时,它不会访问数据库,只是从对象上下文中提取实体,除非我清除/分离或单独重新加载所有实体。
这是正常的,并且在DbContext API固定行为的情况下,因为从一些非常奇怪的原因, DbSet
或DbQuery
都没有公开MergeOption
属性。 对于ObjectContext API,您可以通过在ObjectSet
和ObjectQuery
上公开的MergeOption
设置行为。 因此,如果您想刷新数据库中的值(并丢失更改),您可以执行以下操作:
ObjectContext objectContext = ((IObjectContextAdapter)dbContext).ObjectContext; ObjectSet set = objectContext.CreateObjectSet (); set.MergeOption = MergeOption.OverwriteChanges; List transactions = set.ToList();
如果您只想刷新事务但不想丢失更改,则可以使用MergeOption.PreserveChanges
。
这取决于DefaultContext.Transactions
查询的MergeOption
。 默认值AppendOnly
不会覆盖上下文中已有的对象。 您可以将其更改为OverwriteChanges
以获得您期望的行为。
与上述相关,当我遇到同样的错误时,这就是我降落的地方。 但我想在我的情况下将Merge Option设置为No Tracking 。 当我有一个试图关闭IQueryable的对象跟踪的excel导出方法时,我碰到了这个。 通过我不会改变的大量数据,我不需要任何更改跟踪。
尝试将一些IQueryables转换为类ObjectQuery(但在其他人上取得成功)时,类似下面的代码行将失败。
var y = ((ObjectQuery)query).MergeOption = MergeOption.NoTracking;
相反,我用AsNoTracking的用法取而代之
query = query.AsNoTracking();
回到最初的问题,这可能类似于下面的,在System.Data.Entity中添加的DBQuery上的Extention方法
List transactions = DefaultContext.Transactions.AsNoTracking().ToList();
半相关文章: https : //msdn.microsoft.com/en-us/library/hh949853(v = vs133).aspx