英文:
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的外键,但是,经过多次尝试,我的最终尝试如下,但我仍然无法找到问题。
实际上,这是一个已知的官方问题。在此基础上,我们有两种处理此场景的方法,因此出现了错误:
- 更改一个或多个关系以不进行级联删除。
在这种情况下,我们可以通过为User
关系提供一个可为空的外键属性使UserDetail
和Menu
关系变为可选,例如可以这样做:
.IsRequired(false);
注意:您可以查看我们的官方文档以获取更多详细信息。
- 配置数据库,不进行一个或多个级联删除,然后确保加载所有相关实体,以便EF Core可以执行级联行为。
考虑这种方法,我们可以使User
、UserDetail
和Menu
关系保持必需并配置为级联删除,但仅将此配置应用于已跟踪的实体,而不是数据库。因此,我们可以像下面这样做:
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.
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<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);
}
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论