删除语句与Reference约束冲突

时间:2015-05-29 16:19:49

标签: c# entity-framework

我认为这有一个非常简单的答案。我是实体框架的新手,我正在创建一个由ContactsGroups组成的测试应用程序作为对象/实体。

以下是删除群组的代码:

    private void button_DeleteGroup_Click(object sender, EventArgs e)
    {
        var _selectedGroup = dataGridView_Groups.SelectedRows[0].DataBoundItem as Group;

        try
        {
            cgContext.Groups.Remove(_selectedGroup);
            cgContext.SaveChanges();

            PopulateGroupGrid();
            MessageBox.Show("Successfully deleted group from database!");
        }
        catch(Exception ex) { MessageBox.Show("Failed to delete group from database.\r\n\r\n" + ex); }
    }

如果删除联系人所属的组,为了测试参照完整性,会抛出异常(应该这样):

  

" DELETE语句与REFERENCE约束冲突   " FK_dbo.Contacts_dbo.Groups_Group_Id&#34 ;.冲突发生在   数据库" ContactGroups",table" dbo.Contacts",column   '分组ID&#39 ;.该声明已被终止。"

然后我捕获此异常并向用户显示一条消息。如果我然后去添加新组或联系人或执行任何操作,则事务将失败并出现与以前相同的异常:

  

" DELETE语句与REFERENCE约束冲突   " FK_dbo.Contacts_dbo.Groups_Group_Id&#34 ;.冲突发生在   数据库" ContactGroups",table" dbo.Contacts",column   '分组ID&#39 ;.该声明已被终止。"

因此,显然我不会在发生初始异常时清除/结束事务。我做错了什么或错过了什么?

3 个答案:

答案 0 :(得分:1)

对WithOptional使用WillCascadeOnDelete(true)

  modelBuilder.Entity<Parent>()
  .HasMany<Child>(c => c.Children)
  .WithOptional(x => x.Parent)
  .WillCascadeOnDelete(true);

使用包含

  var adv = db.Adv.Include(b => b.Features)
                  .Include(b => b.AdvDetails)
                  .Include(b => b.AdvGallery)
                  .FirstOrDefault(b => b.Id == id);
  db.Adv.Remove(adv);
  

for .HasMany(...)。WithMany(...)Include is ok

答案 1 :(得分:0)

从实体框架

中的无效实体状态回滚

如果实体框架中存在约束违规或其他无效实体状态,则必须将状态恢复为有效/良好状态,以便继续保持更改。

This answer详细介绍了如何做到这一点。

背景 - 为什么发生FK约束违规

Contacts表和Groups表之间存在外键约束。根据外键(FK)FK_dbo.Contacts_dbo.Groups_Group_Id,每个联系人都有一个组的引用。

在上面的代码中,删除了一个组。在执行此操作之前,应进行检查以确保没有引用该组的联系人,或者应删除该组中的联系人。该方法取决于您的业务逻辑。

删除依赖项后(即通过Contacts.GroupId引用Group的任何联系人),可以在不违反FK的情况下删除该组。

答案 2 :(得分:0)

实体框架也称为持久性存储。因为它会保留实体的状态以及原始值和修改后的值。它实际上是跟踪实体。

EntityStateEntry具有EF中每个实体的条目。因此,当您调用cgContext.Groups.Remove(_selectedGroup)时,它会将实体的状态更改为已删除。

现在,您正在删除与其相关联的人员组。因此,参照完整性不会让您删除_selectedGroup并且您收到错误。但_selectedGroup的状态保留为Deleted。现在,当您添加新组时,请在添加组后调用cgContext.SaveChange()。这会尝试同时保存更改 - 添加新组,并删除_selectedGroup。但同样,删除违反了FK,你也会得到同样的错误。

要使其有效,您可以使用TransactionScope。请参阅用法here