【问题标题】:How to delete an associated object in Entity Framework without having access to the object context如何在实体框架中删除关联对象而不访问对象上下文
【发布时间】:2010-01-19 23:01:33
【问题描述】:

有两个模型,Site 和 Link,其中一个站点有许多链接,我如何从 Site 的方法中删除一个链接,该方法无法访问对象上下文?

我尝试过类似的方法:

public void DeleteFirstLink() {
    var link = LinkSet.First();
    LinkSet.Remove(link);
}

但似乎并没有真正删除链接,而是破坏了关联。由于存在数据库限制,因此会引发此错误:

正在从 AssociationSet 'Sites_have_Links' 中添加或删除关系。对于基数约束,还必须添加或删除相应的“链接”。

我如何真正从数据库中删除链接?

【问题讨论】:

    标签: c# .net entity-framework ado.net objectcontext


    【解决方案1】:

    假设当您调用 DeleteFirstLink() 方法时您的 ObjectContext 不存在,您可以通过在该方法内旋转上下文、附加 Site 实体,然后删除链接来使其工作:

    public void DeleteFirstLink()
    {
      using (ProjectEntities db = new ProjectEntities())
      {
        db.AttachTo("[your site EntitySet name - SiteSet?]", this);
        var link = LinkSet.First();
        db.DeleteObject(link);
        LinkSet.Remove(link);
        db.SaveChanges();
      }
    }
    

    【讨论】:

    • 我很好奇,这行得通吗?我的意思不是说它工作过一次,我的意思是它工作得很好并且不会在极端情况下爆炸。
    • 我看不出它有什么不工作的原因。您需要 ObjectContext 来删除实体,因此您启动一个,附加实体,然后调用“DeleteObject”方法。顺便说一句,“边缘情况”是什么意思?
    【解决方案2】:

    如果没有对象上下文,您无法从数据库中删除任何内容。所有操作都在对象上下文的状态管理器中排队,当您调用 ObjectContext.SaveChanges() 时,这些操作将持久保存到数据库中。没有 SaveChanges,就不会更改数据库。

    【讨论】:

    • 我对队列中的操作很好,我只是希望能够从实体中的方法内部对它们进行排队。
    【解决方案3】:

    首先,如果您能发布更多关于您的班级结构的信息,那就太好了。 Site 类是否有 ObjectContext 对象?然后作为一种快速解决方案,您可以将其传递给 delete 方法并使用 context.DeleteObject() 方法,然后调用 SaveChanges。

    但是,作为一个长期的解决方案,我仍然建议使用 UnitOfWork 模式,并且我将发布指向 article 的链接再次解释它。实现可能会有所不同,但总的来说它可能会解决您的大部分问题(类似于这个)。

    这种方法的美妙之处在于,如果您正确使用它,您可以构建一个小型框架,以后可以在所有 EF 项目中重复使用。

    【讨论】:

    • 不,Site 实体没有 ObjectContext,为什么要呢?
    • 那么,你如何管理 ObjectContext 呢?站点和链接实体是由 EF 生成的吗?他们是继承 EntityObject 还是您使用 POCO 类?您是否通过在单独的文件中使用部分类来扩展站点?
    • 是的,Site 和 Link 是 EF 生成的实体。我想他们继承了EntityObject,但我必须检查一下。我在 Site 的单独文件中有部分类,也许还有 Link(抱歉,现在不在代码前面),但如果没有,我可以制作它们。
    【解决方案4】:
    1. 要使用实体以便修改反映在数据库中,您必须在对象上下文中添加/附加这些实体(根据数据库上下文中的 EF5),然后使用方法 SaveChanges 提交更改。

    2. 是的,在 EF4 中要从物理 SQL 表(不是链接)中删除记录,您需要使用对象 ObjectContext 的方法 DeleteObject,然后使用 SaveChanges,即

      using(ObjectContext context = new ObjectContext)
      {
          /* Find the removed record in object/database context (this will attaches 
           * the record to object/database context)
           * It is recommened to use FirstOrDefault() instead of First() 
           * becase this method can return null if there is no record to delete
           * instead generation of exception in case of using First()
           */
          Link linkToDelete = context.Links.FirstOrDefault(); 
          if(linkToDelete != null) 
          {
              context.DeleteObject(linkToDelete);
              context.SaveChanges();
          }
      }
      
    3. 幸运的是,现在有 EF5 允许从父集合中删除,但前提是关系是一对多

      using(DatabaseContext context = new DatabaseContext)
      {
          Link linkToDelete = context.Links.FirstOrDefault(); 
          if(linkToDelete != null)
          {
              context.Links.Remove(linkToDelete);
              context.SaveChanges();
          }
      }
      
    4. 在任何情况下都不要忘记调用 SaveChanges!

    【讨论】:

      猜你喜欢
      • 2016-12-22
      • 1970-01-01
      • 1970-01-01
      • 2012-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多