【问题标题】:Delete junction table record in Entity Framework Code First (M:M)在 Entity Framework Code First (M:M) 中删除联结表记录
【发布时间】:2018-04-26 10:48:07
【问题描述】:

如何在 Entity Framework 5 中删除联结表中的记录?

在对我的 DataContext 进行逆向工程时,Entity Framework 似乎已经识别了我的联结表并自动将集合添加到我的模型中以表示 M:M 关系。这在添加项目时非常有用,因为我可以简单地构建我的整个实体并且所有内容都可以正确插入。完美。

但是,我很难删除一段关系。例如,一个 Activity 可以有多个与之关联的联系人,并且这是使用由以下列组成的联结表 (dbo.ActivityContacts) 链接的:

  • 活动 ID
  • 联系人 ID

我的 Activity 和 Contact 模型都已由 EF 更新,并使用 Collections 来代表另一个。例如,我的 Activity 模型如下所示:

    public class Activity
    {
        public int ActivityID { get; set; }
        public string Subject { get; set; }
        public virtual ICollection<Contacts> Contacts { get; set; }
    }

在非 EF 环境中,我只需从联结表中删除记录,然后继续我的一天。但是,我似乎无法直接使用 EF 访问联结表,所以我对如何删除记录(关系)有点困惑。

如何从实体框架中的联结表中正确删除记录?

【问题讨论】:

    标签: c# entity-framework many-to-many


    【解决方案1】:

    同意@Chris。

    另一种解决方案是:

    context.Entry(activity).State = EntityState.Deleted;
    

    【讨论】:

      【解决方案2】:

      如果您从关系的任一侧删除关联对象,实体框架应该为您删除记录。

      假设您已从上下文中获得此 Activity 实例,并希望删除具有已知 ID 的特定 Contact

      unwantedContact = context.Contacts.Find(contactID);
      myActivity.Contacts.Remove(unwantedContact);
      
      context.SaveChanges();
      

      应该删除联结表中的记录,除非我很傻。

      【讨论】:

        【解决方案3】:

        ali golshani 在提供解决方案方面做得很好。让我尝试进一步扩展它。在我的场景中,我有两个列表框,您可以在其中向左或向右移动项目(选中或未选中)

        下面的“dto”对象是从客户端发送的。它正在检查列表中每个项目的选定状态。如果有人知道任何改进方法,请留下反馈。

        file_appender selectedAppender = context.file_appender.Find(dto.Id);
        
        int[] ids = dto.Loggers.Where(x => !x.Selected).Select(x => x.Id).ToArray();
        var loggers_to_delete = selectedAppender.logger.Where(x => ids.Contains(x.id));
        loggers_to_delete.ToList().ForEach(x =>
        {
            selectedAppender.logger.Remove(x);
        });
        
        ids = dto.Loggers.Where(x => x.Selected).Select(x => x.Id).ToArray();
        var loggers_to_add = context.logger.Where(x => ids.Contains(x.id));
        loggers_to_add.ToList().ForEach(x =>
        {
            selectedAppender.logger.Add(x);
        });
        

        让我们看另一个例子......这是一个带有嵌入复选框的列表框(稍微简单一点)。老实说,这可能适用于上面的解决方案,以使代码更易于阅读。

        protected void saveRelatedConnectors(test_engine testEngine, List<int> connectorTypes)
            var stepConnectorsToDelete = testEngine.step_connector.Where(x => (connectorTypes.Count == 0) || 
                (connectorTypes.Count != 0 && !connectorTypes.Contains(x.id)));
            stepConnectorsToDelete.ToList().ForEach(x =>
            {
                testEngine.step_connector.Remove(x);
            });
        
            var stepConnectorsToAdd = entities.step_connector.Where(x => connectorTypes.Contains(x.id));
            stepConnectorsToAdd.ToList().ForEach(x =>
            {
                testEngine.step_connector.Add(x);
            });
        
            entities.SaveChanges();
        

        【讨论】:

          【解决方案4】:
          contact_to_delete = context.Contacts.Find(contactID);
          selected_activity = context.Activity.Find(ActivityID);
          context.Entry(selected_activity).Collection("Activity").Load();
          selected_activity.Contacts.Remove(contact_to_delete);
          db.SaveChanges(); 
          

          【讨论】:

          • 你应该详细说明你的答案,简单地发布代码是不礼貌的。
          猜你喜欢
          • 2013-10-28
          • 1970-01-01
          • 1970-01-01
          • 2022-01-18
          • 1970-01-01
          • 2021-12-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多