我已经设置了一个我认为非常简单的数据库。但是我收到以下错误。
在表“User”上引入 FOREIGN KEY 约束“FK_User_Suburb_SuburbId”可能会导致循环或多级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。 无法创建约束或索引。查看之前的错误。
这是我的目录:
using JobsLedger.CATALOG.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
namespace JobsLedger.CATALOG
{
public class CATALOGContext : DbContext
{
public DbSet<Tenant> Tenants { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<State> States { get; set; }
public DbSet<Suburb> Suburbs { get; set; }
public DbSet<CATALOGCounter> Counters { get; set; }
public CATALOGContext(DbContextOptions options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
entity.Relational().TableName = entity.DisplayName();
}
// User
modelBuilder.Entity<User>().Property(u => u.UserName).IsRequired().HasMaxLength(50);
modelBuilder.Entity<User>().Property(u => u.UserFirstName).IsRequired().HasMaxLength(100);
modelBuilder.Entity<User>().Property(u => u.UserLastName).IsRequired().HasMaxLength(100);
modelBuilder.Entity<User>().Property(u => u.Email).IsRequired().HasMaxLength(200);
modelBuilder.Entity<User>().Property(u => u.HashedPassword).IsRequired().HasMaxLength(200);
modelBuilder.Entity<User>().Property(u => u.Salt).IsRequired().HasMaxLength(200);
modelBuilder.Entity<User>()
.HasOne<Suburb>(s => s.Suburb)
.WithMany(u => u.Users)
.HasForeignKey(u => u.SuburbId)
.IsRequired(false);
// Role
modelBuilder.Entity<Role>().Property(r => r.Name).IsRequired().HasMaxLength(50);
modelBuilder.Entity<Role>()
.HasOne<User>(u => u.User)
.WithOne(r => r.Role)
.HasForeignKey<User>(u => u.RoleId);
// TenantAccount
modelBuilder.Entity<Tenant>().Property(t => t.TenantNo).HasMaxLength(20);
modelBuilder.Entity<Tenant>().Property(t => t.Company).HasMaxLength(100).IsRequired();
modelBuilder.Entity<Tenant>().Property(t => t.ContactLastName).HasDefaultValue(false).IsRequired();
modelBuilder.Entity<Tenant>().Property(t => t.Email).HasMaxLength(500).IsRequired();
modelBuilder.Entity<Tenant>().Property(t => t.MobilePhone).HasMaxLength(20).IsRequired();
modelBuilder.Entity<Tenant>().Property(t => t.OfficePhone).HasMaxLength(20);
modelBuilder.Entity<Tenant>().Property(t => t.CompanyEmail).HasMaxLength(500);
modelBuilder.Entity<Tenant>().Property(t => t.Address1).HasMaxLength(500);
modelBuilder.Entity<Tenant>().Property(t => t.Address2).HasMaxLength(500);
modelBuilder.Entity<Tenant>().Property(t => t.ABN).HasMaxLength(14);
modelBuilder.Entity<Tenant>().Property(t => t.Database).HasMaxLength(100).IsRequired();
modelBuilder.Entity<Tenant>().Property(t => t.IsLocked).HasDefaultValue(false);
modelBuilder.Entity<Tenant>()
.HasOne<User>(s => s.User)
.WithMany(ta => ta.Tenants)
.HasForeignKey(u => u.UserId);
modelBuilder.Entity<Tenant>()
.HasOne(s => s.Suburb)
.WithMany(ta => ta.Tenants)
.HasForeignKey(ta => ta.SuburbId);
// State
modelBuilder.Entity<State>().Property(s => s.StateShortName).HasMaxLength(3).IsRequired();
modelBuilder.Entity<State>().Property(s => s.StateName).HasMaxLength(30).IsRequired();
// Suburb
modelBuilder.Entity<Suburb>().Property(s => s.SuburbName).HasMaxLength(3).IsRequired();
modelBuilder.Entity<Suburb>().Property(s => s.PostCode).HasMaxLength(30).IsRequired();
modelBuilder.Entity<Suburb>()
.HasOne<State>(s => s.State)
.WithMany(su => su.Suburbs)
.HasForeignKey(st => st.StateId);
}
}
}
这是我的用户:
...
public int? SuburbId { get; set; }
public Suburb Suburb { get; set; }
public int RoleId { get; set; }
public Role Role { get; set; }
public virtual ICollection<Tenant> Tenants { get; set; }
这是我的郊区,也被提到过..
想知道是否有人会强调为什么迁移会起作用,但是当我尝试启动数据库时,它会出现上述错误..
西蒙
错误已经说明了您需要做什么。指定当有一个动作时它必须做什么。您应该将
.OnDelete()
方法添加到每个外键定义中。
modelBuilder.Entity<Tenant>()
.HasOne<User>(s => s.User)
.WithMany(ta => ta.Tenants)
.HasForeignKey(u => u.UserId)
.OnDelete(DeleteBehavior.Restrict);
欲了解更多信息,请阅读https://www.learnentityframeworkcore.com/configuration/ Fluent-api/ondelete-method
您的
User
实体 ForeignFey
Fluent API 配置应如下所示:
modelBuilder.Entity<User>()
.HasOne<Suburb>(s => s.Suburb)
.WithMany(u => u.Users)
.HasForeignKey(u => u.SuburbId)
.IsRequired(false);
.OnDelete(DeleteBehavior.Restrict); // <-- Here it is
对于发现这个问题的其他人来说,这就足够了:
modelBuilder.Entity<User>()
.HasOne(u => u.Suburb)
.WithMany(s => s.Users)
.OnDelete(DeleteBehavior.Restrict);
如果您不想在
Suburb
中使用 Users
列出属性,您也可以这样做:
modelBuilder.Entity<User>()
.HasOne(u => u.Suburb)
.WithMany()
.OnDelete(DeleteBehavior.Restrict);
上面的答案是正确的,但让我解释一下为什么您会遇到这个问题。
基本上,User实体当前与Suburb和Role都有关系,因此不能进行级联删除,这会导致冲突。
假设您删除了一个角色,它也会删除用户,但是那么郊区呢?您现在可以看到 Suburb 没有与任何东西绑定,这就是 EF Core 阻止这种行为的原因。您必须指定 NO ACTION,以便删除角色或郊区时用户不会受到影响。 当一个实体与多个其他实体有关系时,这是一个非常常见的问题。
在这种情况下,仅仅因为角色或郊区不再存在而删除用户是没有意义的。