.NET 7/ EF Core 7:我们有一个跟踪数据库更改的进程,但我无法控制它。这是一个黑匣子。 我能控制的是保存这些更改的方法。在我的例程中,我想省略不是来自两个核心表的条目。这是从跟踪器中“清除”这些条目的好方法吗?或者有更容易接受的方法吗?
我们的数据库相当小,每个表都包含
// first we only want to commit changes to Schedule and Vacation ONLY so get those entries which are not part of that set.
var unDbSets = context.ChangeTracker.Entries()
.Where(e => e.Entity is not Schedule && e.Entity is not Vacation)
.Where(p => p.State == EntityState.Added || p.State == EntityState.Deleted || p.State == EntityState.Modified)
.ToList();
foreach (var unDbSet in unDbSets)
{
if (unDbSet.State == EntityState.Added)
{
// entity was never in the DB so we just try detaching it. this way EF will stop tracking it and will not take any
// actions to serialize changes against DB.
// note: we had this originally to Unchanged but that throws an exception
unDbSet.State = EntityState.Detached;
}
else
{
// entity was in the DB so we just change the state to unchanged and it will not do anything with it and EF will leave
// it in its original state in the DB.
unDbSet.State = EntityState.Unchanged;
}
}
// finally save the tracker changes
context.SaveChanges();
< 10k records.
即
public interface IEditableEntity {}
这可以绑定到任何基实体类,如果您在 DbContext 中合并处理这些属性,您可能必须集中 LastModifiedBy 和 LastModifiedDateTime 等属性。然后处理拒绝编辑或插入等问题。我倾向于单独处理这些问题,因为我可能想报告有关被丢弃的更改类型的详细信息。
var unAllowedUpdates = ChangeTracker.Entries().Any(x => x.State == EntityState.Modified
&& !typeof(IEditableEntity).IsAssignableFrom(x.GetType())));
最终,您已经完成了从更改跟踪器中删除这些项目的操作,方法是分离添加并将修改设置为未更改。但是,如果您想完全放弃这些更改,如果保存后可以针对 DbContext 实例运行其他查询,则还应该在
ChangeTracker.Clear()
完成后调用
SaveChanges()
。例如,假设我有一个包含这些时间表的旅行实体,并且出于某种原因可以更新我不希望保留的旅行,但我确实希望保留对时间表的添加和更新。保存数据时,我可以将 Trip 设置为 Unchanged,这样这些更改就不会被写入,但是如果代码碰巧从 DbContext 再次加载行程,它仍然会在跟踪缓存中接收我修改过的(但未更改的) Trip 实体,而不是而不是拉取真实的数据状态。如果您打算放弃更改,但仍然可以在保存后查看可能的修改(实际上并未持久化),那么您不想清除更改跟踪器,但如果您想确保放弃的更改反映在来自的任何进一步调用中如果更改被丢弃/忽略,那么您应该在保存后清除更改跟踪器。