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

Vac*_*ano 7 .net c# entity-framework entity-framework-4

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

但实体框架正在努力做到这一点.我可以插入到一个集合(在我的业务层中)而不引用ObjectContext:

order.Containers.Add(new Container { ContainerId = containerId, Order = order });
Run Code Online (Sandbox Code Playgroud)

SaveChanges()在数据层中进行操作时,这样可以节省很多时间.

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

 delContainers.ForEach(container => order.Containers.Remove(container));
Run Code Online (Sandbox Code Playgroud)

然后,当我打电话时,SaveChanges()我得到一个异常告诉我,我需要删除对象以及引用.

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

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

有谁知道这样做的方法?

更新:

我试过这个:

// Add an event when Save Changes is called
this.ObjectContext.SavingChanges += OnSavingChanges; 
Run Code Online (Sandbox Code Playgroud)

...

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
       }
   }
}
Run Code Online (Sandbox Code Playgroud)

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

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

Lad*_*nka 5

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

要使其工作,您的实体必须启用动态更改跟踪(所有属性必须是虚拟的并且实体必须是代理的),或者您必须手动调用DetectChanges.

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