c# – 实体框架6:检测关系变化

前端之家收集整理的这篇文章主要介绍了c# – 实体框架6:检测关系变化前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在我的DbContext子类中,我重写了SaveChanges()方法,因此我可以实现一种类似触发器的功能(在实际保存更改之前).
现在,在某些触发器中,有必要检测某些关系是否已经改变,无论多对多,一对一/零等.

我已经阅读了互联网上的一些帖子,包括本网站上的一些帖子,提到DbContext API没有公开任何获取关系信息的方法.
但是,ObjectContext应该能够.

我的SaveChanges方法

  1. public override int SaveChanges()
  2. {
  3. IEntity entity;
  4. ChangeTracker.DetectChanges();
  5.  
  6. var stateManager = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager;
  7. var added = stateManager.GetObjectStateEntries(EntityState.Added).ToList();
  8. var updated = stateManager.GetObjectStateEntries(EntityState.Modified).ToList();
  9. var deleted = stateManager.GetObjectStateEntries(EntityState.Deleted).ToList();
  10. var unchanged = stateManager.GetObjectStateEntries(EntityState.Unchanged).ToList();
  11.  
  12. while ((entity = _entitiesRequiringTriggering.FirstOrDefault(x => x.Value).Key) != null)
  13. {
  14. _entitiesRequiringTriggering[entity] = false;
  15. var entry = ChangeTracker.Entries<IEntity>().SingleOrDefault(x => x.State != EntityState.Unchanged && x.Entity == entity);
  16. if (entry == null) continue;
  17. var trigger = Triggers.Triggers.GetTriggerForEntity(entry.Entity,this);
  18. if (trigger == null) continue;
  19. trigger.BeforeSave(entry.Entity);
  20. switch (entry.State)
  21. {
  22. case EntityState.Added:
  23. trigger.BeforeAdd(entry.Entity);
  24. break;
  25. case EntityState.Modified:
  26. trigger.BeforeUpdate(entry.Entity);
  27. break;
  28. case EntityState.Deleted:
  29. trigger.BeforeDelete(entry.Entity);
  30. break;
  31. }
  32. }
  33. return base.SaveChanges();
  34. }

请注意添加,更新,删除和更改的四个变量.
根据我到目前为止所发现的,GetObjectStateEntries应该返回ObjectStateEntry的集合,该集合具有IsRelationship属性.

我在测试应用程序中运行以下代码

  1. using (var db = container.Resolve<IDatabaseContext>())
  2. {
  3. var cus = db.Query<Customer>().Single(x => x.Id == 1);
  4. var newAddress = db.Query<Address>().Single(x => x.Id == 5);
  5.  
  6. cus.Address = newAddress; //also sets the foreign key property Customer.AddressId to its new corresponding value
  7. db.SaveChanges();
  8. }

当我在调用后检查SaveChanges中的代码时,我得到了预期的结果:
一个结果在更新列表中,Customer对象.
但在任何时候,我都没有获得关系(一对一)Customer_Address的ObjectStateEntry.

我需要能够在关系发生变化时如前所述进行检测.
对于正常的标量属性,您可以这样做:

  1. var changed = DbEntry.Property(x => x.Name).OriginalValue == DbEntry.Property(x => x.Name).CurrentValue;

但对于不明显起作用的参考属性.
有任何想法吗?

解决方法

您可以使用此ExtensionMethod获取已更改的关系列表
  1. public static class DbContextExtensions
  2. {
  3. public static IEnumerable<Tuple<object,object>> GetRelationships(
  4. this DbContext context)
  5. {
  6. return GetAddedRelationships(context)
  7. .Union(GetDeletedRelationships(context));
  8. }
  9.  
  10. public static IEnumerable<Tuple<object,object>> GetAddedRelationships(
  11. this DbContext context)
  12. {
  13. return GetRelationships(context,EntityState.Added,(e,i) => e.CurrentValues[i]);
  14. }
  15.  
  16. public static IEnumerable<Tuple<object,object>> GetDeletedRelationships(
  17. this DbContext context)
  18. {
  19. return GetRelationships(context,EntityState.Deleted,i) => e.OriginalValues[i]);
  20. }
  21.  
  22. private static IEnumerable<Tuple<object,object>> GetRelationships(
  23. this DbContext context,EntityState relationshipState,Func<ObjectStateEntry,int,object> getValue)
  24. {
  25. context.ChangeTracker.DetectChanges();
  26. var objectContext = ((IObjectContextAdapter)context).ObjectContext;
  27.  
  28. return objectContext.ObjectStateManager
  29. .GetObjectStateEntries(relationshipState)
  30. .Where(e => e.IsRelationship)
  31. .Select(
  32. e => Tuple.Create(
  33. objectContext.GetObjectByKey((EntityKey)getValue(e,0)),objectContext.GetObjectByKey((EntityKey)getValue(e,1))));
  34. }
  35. }

猜你在找的C#相关文章