“Foreign Key可能导致循环或多重级联路径 – EF”

huangapple go评论107阅读模式
英文:

Foreign Key may cause cycles or multiple cascade paths - EF

问题

以下是翻译好的部分:

这是我的第一个ASP.NET Core 6 Web API与EF。我想在`UserDetail`和`Menu`上创建FK `PersonalId`,然而,经过多次尝试,我的最终尝试如下,但我仍然无法找到问题所在。

这些是模型:

    public class User
    {
        public int Id { get; set; }

        public UserDetail? UserDetail { get; set; }

        public int PersonalId { get; set; }
        public string? Password { get; set; }
    }

    public class UserDetail
    {
        [Key]
        public int Id { get; set; }

        public int PersonalId { get; set; }

        public int UserId { get; set; }
        public User? User { get; set; }

        public UserDetailsRole Role { get; set; }

        public string? FullName { get; set; }

        public Menu? Menu { get; set; }
    }

    public class Menu
    {
        [Key]
        public int Id { get; set; }

        public int PersonalId { get; set; }

        public int UserDetailId { get; set; }
        public UserDetail? UserDetail { get; set; }

        [MaxLength(20)]
        public string? Monday { get; set; }
        .....
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>()
            .HasOne(u => u.UserDetail)
            .WithOne(ud => ud.User)
            .HasForeignKey<User>(u => u.PersonalId);

        modelBuilder.Entity<Menu>()
            .HasOne(m => m.UserDetail)
            .WithOne()
            .HasForeignKey<Menu>(m => m.PersonalId);

        modelBuilder.Entity<UserDetail>()
            .HasOne(ud => ud.User)
            .WithOne(u => u.UserDetail)
            .HasForeignKey<User>(u => u.Id)
            .OnDelete(DeleteBehavior.NoAction);
    }

我收到以下错误消息:

> 引入FOREIGN KEY约束'FK_UserDetails_Users_UserId'到表'UserDetails'可能导致循环或多重级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束

谢谢您提前的帮助。

更新-问题解决:

    modelBuilder.Entity<User>()
                .HasOne(u => u.UserDetail)
                .WithOne(ud => ud.User)
                .HasForeignKey<User>(u => u.PersonalId)
                .OnDelete(DeleteBehavior.Restrict)
                .IsRequired(false);
    
            modelBuilder.Entity<UserDetail>()
                .HasOne(u => u.Menu)
                .WithOne(ud => ud.UserDetail)
                .HasForeignKey<Menu>(u => u.PersonalId)
                .OnDelete(DeleteBehavior.Restrict)
                .IsRequired(false);
    
            modelBuilder.Entity<UserDetail>()
                .HasOne(u => u.Transit)
                .WithOne(ud => ud.UserDetail)
                .HasForeignKey<Transit>(u => u.PersonalId)
                .OnDelete(DeleteBehavior.Restrict)
                .IsRequired(false);
英文:

This is my first ASP.NET Core 6 Web API with EF. I want to make FK PersonalId on UserDetail and Menu, however, from multiple iterations my final attempt is below but I'm still unable to find the issue.

These are the models:

public class User
{
public int Id { get; set; }
public UserDetail? UserDetail { get; set; }
public int PersonalId { get; set; }
public string? Password { get; set; }
}
public class UserDetail
{
[Key]
public int Id { get; set; }
public int PersonalId { get; set; }
public int UserId { get; set; }
public User? User { get; set; }
public UserDetailsRole Role { get; set; }
public string? FullName { get; set; }
public Menu? Menu { get; set; }
}
public class Menu
{
[Key]
public int Id { get; set; }
public int PersonalId { get; set; }
public int UserDetailId { get; set; }
public UserDetail? UserDetail { get; set; }
[MaxLength(20)]
public string? Monday { get; set; }
.....
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.HasOne(u => u.UserDetail)
.WithOne(ud => ud.User)
.HasForeignKey<User>(u => u.PersonalId);
modelBuilder.Entity<Menu>()
.HasOne(m => m.UserDetail)
.WithOne()
.HasForeignKey<Menu>(m => m.PersonalId);
modelBuilder.Entity<UserDetail>()
.HasOne(ud => ud.User)
.WithOne(u => u.UserDetail)
.HasForeignKey<User>(u => u.Id)
.OnDelete(DeleteBehavior.NoAction);
}

I'm getting the following error message:

> Introducing FOREIGN KEY constraint 'FK_UserDetails_Users_UserId' on table 'UserDetails' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

Thank you in advance for your help.

Update-Solved:

modelBuilder.Entity<User>()
.HasOne(u => u.UserDetail)
.WithOne(ud => ud.User)
.HasForeignKey<User>(u => u.PersonalId)
.OnDelete(DeleteBehavior.Restrict)
.IsRequired(false);
modelBuilder.Entity<UserDetail>()
.HasOne(u => u.Menu)
.WithOne(ud => ud.UserDetail)
.HasForeignKey<Menu>(u => u.PersonalId)
.OnDelete(DeleteBehavior.Restrict)
.IsRequired(false);
modelBuilder.Entity<UserDetail>()
.HasOne(u => u.Transit)
.WithOne(ud => ud.UserDetail)
.HasForeignKey<Transit>(u => u.PersonalId)
.OnDelete(DeleteBehavior.Restrict)
.IsRequired(false);

答案1

得分: 1

这是我的第一个Web API .Net 6.0应用程序,使用EF。我想在UserDetail和Menu上创建一个名为PersonalId的外键,但是,经过多次尝试,我的最终尝试如下,但我仍然无法找到问题。

实际上,这是一个已知的官方问题。在此基础上,我们有两种处理此场景的方法,因此出现了错误:

  1. 更改一个或多个关系以不进行级联删除。

在这种情况下,我们可以通过为User关系提供一个可为空的外键属性使UserDetailMenu关系变为可选,例如可以这样做:

.IsRequired(false);

注意:您可以查看我们的官方文档以获取更多详细信息。

  1. 配置数据库,不进行一个或多个级联删除,然后确保加载所有相关实体,以便EF Core可以执行级联行为。

考虑这种方法,我们可以使UserUserDetailMenu关系保持必需并配置为级联删除,但仅将此配置应用于已跟踪的实体,而不是数据库。因此,我们可以像下面这样做:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>()
        .HasOne(u => u.UserDetail)
        .WithOne(ud => ud.User)
        .HasForeignKey<User>(u => u.PersonalId)
        .IsRequired(false);

    modelBuilder.Entity<Menu>()
        .HasOne(m => m.UserDetail)
        .WithOne()
        .HasForeignKey<Menu>(m => m.PersonalId)
        .IsRequired(false);

    modelBuilder.Entity<UserDetail>()
        .HasOne(ud => ud.User)
        .WithOne(u => u.UserDetail)
        .HasForeignKey<User>(u => u.Id)
        .OnDelete(DeleteBehavior.Restrict)
        .IsRequired(false);
}

注意:正如您可能已经知道的那样,OnDelete(DeleteBehavior.ClientCascade);ClientCascade允许DBContext删除实体,即使存在循环引用锁定。请阅读官方指南以获取更多详细信息。

英文:

> This is my first Web API .Net 6.0 application with EF. I want to make
> FK PersonalId on UserDetail and Menu, however, from multiple
> iterations my final attempt is below but I'm still unable to find the
> issue.

“Foreign Key可能导致循环或多重级联路径 – EF”

Actually,this is officially known issue. On top of this, We have two ways to handle this scenario therefore, the error:

1. Change one or more of the relationships to not cascade delete.

In this scenario, we could make the User relationship with UserDetail and Menu optional by giving it a nullable foreign key property: for instance we can do something like:

.IsRequired(false);

Note: You can check our official document for more details.

2. Configure the database without one or more of these cascade deletes,
then ensure all dependent entities are loaded so that EF Core can
perform the cascading behavior.

Considering this approach we can keep the User, UserDetail and Menu relationship required and configured for cascade delete, but make this configuration only apply to tracked entities, not the database: So we can do somethng like below:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity&lt;User&gt;()
.HasOne(u =&gt; u.UserDetail)
.WithOne(ud =&gt; ud.User)
.HasForeignKey&lt;User&gt;(u =&gt; u.PersonalId)
.IsRequired(false);
modelBuilder.Entity&lt;Menu&gt;()
.HasOne(m =&gt; m.UserDetail)
.WithOne()
.HasForeignKey&lt;Menu&gt;(m =&gt; m.PersonalId)
.IsRequired(false);
modelBuilder.Entity&lt;UserDetail&gt;()
.HasOne(ud =&gt; ud.User)
.WithOne(u =&gt; u.UserDetail)
.HasForeignKey&lt;User&gt;(u =&gt; u.Id)
.OnDelete(DeleteBehavior.Restrict)
.IsRequired(false);
}

Note: As you may know OnDelete(DeleteBehavior.ClientCascade); or ClientCascade allows the DBContext to delete entities even if there is a cyclic ref or LOCK on it. Please read the official guideline for more details here

huangapple
  • 本文由 发表于 2023年7月3日 06:13:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76600981.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定