使用Entity Framework更改跟踪器

时间:2015-10-12 18:31:48

标签: c# entity-framework entity-framework-6

出于审计/历史目的,我使用实体框架更改跟踪器在编写更改之前确定已更改的内容并序列化更改。我可以通过调用this.ChangeTracker.Entries()衍生产品中的DbContext并查看标记为EntityState.AddedEntityState.DeletedEntityState.Modified的任何值来获取已更改的实体。这一切都很有效。

我的问题是此方法无法跟踪对EF对象集合的更改(例如,ICollection<Person>对象上的PersonGroup属性。)

我确定EF上下文必须以某种方式跟踪这一点 - 毕竟数据库更新还有什么用呢?但我可以使用吗?

2 个答案:

答案 0 :(得分:3)

您正在寻找的是关系变化跟踪。您可以在基础ObjectStateManager的{​​{1}}中找到它,以下是您获得所有相关关系的方式:

ObjectContext

答案 1 :(得分:3)

事实证明,您可以了解与此代码的关系(假设它在您的DbContext衍生品中运行):

((IObjectContextAdapter) this).ObjectContext.ObjectStateManager
     .GetObjectStateEntries(EntityState.Added)
     .Where(e => e.IsRelationship)
     .Select(r => new {EntityKeyInfo = r.CurrentValues[0], 
                       CollectionMemberKeyInfo = r.CurrentValues[1], r.State});

显然你可以根据你的需要来调整它,并且它可以帮你做一些有用的东西。前两个CurrentValues条目表示EntityKey对象,它们允许您获取相关实体的ID。

如果您想处理已删除的实体,这将无效,您需要使用反射。您可以查看内部属性CurrentValues[0]CurrentValues[1],而不是Key0Key1,这些属性是在编译时无法访问的内部类中定义的。这将有效:r.GetType().GetProperty("Key0", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(r, new object[0])。请注意,这可能不是预期用途,可能会随时爆发。