有没有办法找到已删除关系的所有实体?

我试图让我的业务逻辑不知道我的数据层的内部工作方式,反之亦然。

但entity framework正在努力做到这一点。 我可以插入到一个集合(在我的业务层中)而不引用ObjectContext:

order.Containers.Add(new Container { ContainerId = containerId, Order = order }); 

当在数据层中执行SaveChanges()时,这可以节省很多时间。

但是要从集合中删除项目,我需要对ObjectContext的引用。 (我在本指南中删除了EF实体的情况#1。)如果我这样做:

  delContainers.ForEach(container => order.Containers.Remove(container)); 

然后,当我调用SaveChanges()我得到一个exception,告诉我我需要删除对象以及引用。

所以,我认为它的选择是:

  1. 将委托传递给将调用Entity Framework ObjectContext Delete方法的业务逻辑。
  2. 或者(我希望)找到一种方法来获取已删除其引用并实际删除它们的所有实体。 (在我的数据层中调用SaveChanges()之前。)

有谁知道这样做的方法?

更新:

我试过这个:

 // Add an event when Save Changes is called this.ObjectContext.SavingChanges += OnSavingChanges; 

 void OnSavingChanges(object sender, EventArgs e) { var objectStateEntries = ObjectContext.ObjectStateManager .GetObjectStateEntries(EntityState.Deleted); foreach (var objectStateEntry in objectStateEntries) { if (objectStateEntry.IsRelationship) { // Find some way to delete the related entity } } } 

但即使我删除了一个关系,也没有删除的项目为空。

(我也尝试查看所有项目,我的关系不在那里。显然,我没有得到关于ObjectStateManager的基本信息。)

EF的正确解决方案是来自链接文章的第3点。 这意味着将FK传播到主体实体到依赖实体的PK。 这将形成一种称为识别关系的东西,当从父实体中移除依赖实体时,它会自动删除它。

如果你不想改变你的模型并且仍然希望以持久性无知的方式实现它,你可能可以,但它只适用于独立的关联 。 一些初步实现至少适用于我的简单测试解决方案:

 public partial class YourObjectContext { public override int SaveChanges(SaveOptions options) { foreach (ObjectStateEntry relationEntry in ObjectStateManager .GetObjectStateEntries(EntityState.Deleted) .Where(e => e.IsRelationship)) { var entry = GetEntityEntryFromRelation(relationEntry, 0); // Find representation of the relation IRelatedEnd relatedEnd = entry.RelationshipManager .GetAllRelatedEnds() .First(r => r.RelationshipSet == relationEntry.EntitySet); RelationshipType relationshipType = relatedEnd.RelationshipSet.ElementType; if (!SkipDeletion(relationshipType)) { // Now we know that model is inconsistent and entity on many side must be deleted if (!(relatedEnd is EntityReference)) // related end is many side { entry = GetEntityEntryFromRelation(relationEntry, 1); } if (entry.State != EntityState.Deleted) { context.DeleteObject(entry.Entity); } } } return base.SaveChanges(); } private ObjectStateEntry GetEntityEntryFromRelation(ObjectStateEntry relationEntry, int index) { var firstKey = (EntityKey) relationEntry.OriginalValues[index]; ObjectStateEntry entry = ObjectStateManager.GetObjectStateEntry(firstKey); return entry; } private bool SkipDeletion(RelationshipType relationshipType) { return // Many-to-many relationshipType.RelationshipEndMembers.All( r => r.RelationshipMultiplicity == RelationshipMultiplicity.Many) || // ZeroOrOne-to-many relationshipType.RelationshipEndMembers.Any( r => r.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne); } } 

要使其正常工作,必须启用实体以进行动态更改跟踪(所有属性必须为虚拟且实体必须代理),或者您必须手动调用DetectChanges

在外键关联的情况下,情况可能会更糟,因为您在状态管理器中找不到任何已删除的关系。 您必须手动跟踪集合或密钥的更改并进行比较以查找差异(我不确定如何以通用方式执行)外键关联IMHO需要识别关系。 使用FK属性已经意味着您在模型中包含了额外的持久性依赖性。

一种方法是在数据层中编写更改处理程序:

  private void ContainersChanged(object sender, CollectionChangeEventArgs e) { // Check for a related reference being removed. if (e.Action == CollectionChangeAction.Remove) { Context.DeleteObject(e.Element); } } 

你可以在很多地方连接它 – 在你的对象的构造函数或存储库获取或SavingChanges或任何地方:

  entity.Containers.AssociationChanged += new CollectionChangeEventHandler(ContainersChanged); 

现在,您可以从其他地方删除关联,它将“级联”到实体。