【问题标题】:Association severed exception when trying to delete a model with relationship尝试删除具有关系的模型时关联断开异常
【发布时间】:2021-02-02 02:25:03
【问题描述】:

这是我的模型(缩写)

用户:

public partial class User
{
    public int Id { get; set; }
    public virtual BusinessOwner BusinessOwner { get; set; }
    //rest of code
}

和 BusinessOwner,它对用户有一个外键 (User.Id = BusinessOwner.UserId) 这意味着企业主必须是用户。

企业主:

 public partial class BusinessOwner
{
    public int UserId { get; set; }
    public virtual User User { get; set; }
    //rest of code
}

在一个场景中,我必须删除一个用户,所以我得到了用户并包含了这样的关系:

 public User GetByIdEager(int id)
    {
        return _context.User.Where(u => u.Id == id && u.DeletedAt == null)
            .Include(u => u.BusinessOwner)
            .FirstOrDefault();
    }

这是我的控制器:

  public class UserController : ControllerBase
  {
      [HttpDelete("id")]
      public ActionResult Delete(int id)
      {
          User user = GetByIdEager(id);
          _context.User.Remove(user);
          _context.SaveChanges();
          return Ok();
      }
  }

调用_context.User.Remove(user);时出现以下异常

实体类型Users和BusinessOwners之间的关联已经 已被切断,但该关系要么标记为“必需”,要么 隐式需要,因为外键不可为空。如果 当需要关系时,应删除依赖/子实体 被切断,然后设置关系以使用级联删除

即使我在检索用户时包含了 BusinessOwner。有人能告诉我为什么会这样吗?我该如何解决?

【问题讨论】:

  • 欢迎来到 Stack Overflow。请通过tour 了解 Stack Overflow 的工作原理,并阅读How to Ask 了解如何提高问题的质量。然后edit你的问题包含你的源代码作为minimal reproducible example,它可以被其他人编译和测试。
  • 好的,感谢您指出这一点。 @Progman
  • 你为这两个表设置了映射吗?
  • 不,我想我不需要。当我调试并单击 User.BusinessOwner 时,我看到它已成功加载。为什么我需要映射? @osmanRahimi

标签: c# .net-core entity-framework-core entity-relationship ef-core-3.1


【解决方案1】:

好的,我想我知道出了什么问题,所以我发布它以防其他人也遇到这个问题。

docs ,原来有多种关系:Cascade、ClientSetNull、SetNull 和 Restrict。并且这些关系中的每一个都有一个删除行为。

在高层次上:

  • 如果您的实体没有父级就无法存在,并且您希望 EF 自动删除子级,那么 使用级联。
  • 没有父级就无法存在的实体通常使用必需的关系,其中默认为 Cascade。
  • 如果您的实体可能有也可能没有父实体,并且您希望 EF 为您清空外键,那么 使用 ClientSetNull
  • 可以在没有父级的情况下存在的实体通常使用可选关系,其中 ClientSetNull 是默认关系。
  • 如果您希望数据库也尝试将空值传播到子外键,即使未加载子实体,请使用 置空。但是,请注意,数据库必须支持这一点,并且
    像这样配置数据库可能会导致其他限制,
    这在实践中常常使这个选项不切实际。这就是为什么
    SetNull 不是默认设置。
  • 如果您不希望 EF Core 自动删除实体或自动清除外键,请使用 Restrict。请注意
    这要求您的代码保留子实体及其外国
    手动同步键值,否则将出现约束异常
    扔了。

然后我去我的DBContext,发现关系自动设置为ClientSetNull,这就是为什么我得到异常:BusinessOwner中的UserId字段设置为NULL,并且表中不允许空值那个领域。 解决方案是将删除行为设置为Cascade 而不是ClientSetNull。像这样 : 在我的 DbContext 中:

entity.HasOne(d => d.User)
                    .WithOne(p => p.BusinessOwner)
                    .HasForeignKey<BusinessOwner>(d => d.UserId)
                    .OnDelete(DeleteBehavior.Cascade)
                    .HasConstraintName("FK__business___user___7E37BEF6");

现在每当我删除用户时,企业主都会被删除。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多