在表中引入FOREIGN KEY约束时,如何避免循环



我在EF Core 6中使用代码优先方法来构建数据库及其表。问题是,当我更新数据库时,我会得到一个关于循环或多个级联路径的错误。我搜索了同样的问题,但没有一个能解决我的问题。我的实体类是:

public class User
{
[Key]
public int UserId { get; set; }
[Required]
[DataType(DataType.Text)]
public string Username { get; set; }
[Required]
[DataType(DataType.Text)]
public string Password { get; set; }
[Required]
[DataType(DataType.Text)]
public string UserRole { get; set; }
[Required]
public bool IsActive { get; set; }
[Required]
public bool CanAccessNotifications { get; set; }
[Required]
public bool CanAccessMessages { get; set; }
[Required]
public bool CanAccessFiles { get; set; }
[Required]
public bool CanAccessPmDatabase { get; set; }
[Required]
public bool CanMakeChangesToPmDatabase { get; set; }
[Required]
public bool IsLocked { get; set; }
[Required]
public bool CanLocked { get; set; }
//Navigation properties
public virtual CostCenter CostCenter { get; set; }
public virtual List<PmSchedule> PmSchedules { get; set; }
}
public class ServiceType
{
[Key]
public int ServiceTypeId { get; set; }
[Required]
[DataType(DataType.Text)]
public string Title { get; set; }
[Required]
public bool IsActive { get; set; } = true;
//Navigation properties
public virtual List<PmDataSet> PmDataSets { get; set; }
public virtual List<PmSchedule> PmSchedules { get; set; }
}
public class PmSchedule
{
[Key]
public long PmScheduleId { get; set; }
[Required]
public long PmNumber { get; set; }
[Required]
[DataType(DataType.DateTime)]
public DateTime ScheduledStartDate { get; set; }
[Required]
[DataType(DataType.DateTime)]
public DateTime ScheduledEndDate { get; set; }
[Required]
[DataType(DataType.Text)]
public string MainFileName { get; set; }
[DataType(DataType.Text)]
public string? UploadedFileName { get; set; }
[Required]
public int MainUploader { get; set; }
public int? Uploader { get; set; }
[DataType(DataType.DateTime)]
public DateTime? CompletionDate { get; set; }
[Required]
[DataType(DataType.Text)]
public string? Status { get; set; }
//Navigation properties
public virtual CostCenter CostCenter { get; set; }
public virtual ServiceType ServiceType { get; set; }
}
public class PmDataSet
{
[Key]
public long PmDataSetId { get; set; }
[Required]
public long PmNumber { get; set; }
[Required]
[DataType(DataType.DateTime)]
public DateTime ScheduledStartDate { get; set; }
[Required]
[DataType(DataType.DateTime)]
public DateTime ScheduledEndDate { get; set; }
[Required]
[DataType(DataType.Text)]
public string WorkOrderNumber { get; set; }
[Required]
[DataType(DataType.Text)]
public string Priority { get; set; }
[Required]
[DataType(DataType.Text)]
public string Activity { get; set; }
[DataType(DataType.DateTime)]
public DateTime? StartTime { get; set; }
[DataType(DataType.DateTime)]
public DateTime? EndTime { get; set; }
[Required]
public int ActualDuration { get; set; }
[Required]
public int StandardDuration { get; set; }
[Required]
[DataType(DataType.Text)]
public string Executor { get; set; }
[DataType(DataType.Text)]
public string? Expaination { get; set; }

//Navigation properties
public virtual ServiceType ServiceType { get; set; }
public virtual CostCenter CostCenter { get; set; }
public virtual Equipment Equipment { get; set; }
}
public class Equipment
{
[Key]
public long EquipmentId { get; set; }
[Required]
[DataType(DataType.Text)]
public string EquipmentCode { get; set; }
[Required]
[DataType(DataType.Text)]
public string EquipmentTitle { get; set; }
//Navigation properties
public virtual CostCenter CostCenter { get; set; }
public virtual List<PmDataSet> PmDataSets { get; set; }
}
public class CostCenter
{
[Key]
public int CostCenterId { get; set; }
[Required]
[DataType(DataType.Text)]
public string Title { get; set; }
[Required]
public bool IsActive { get; set; } = true;

//Navigation properties
public virtual List<PmDataSet>? PmDataSets { get; set; }
public virtual List<PmSchedule>? PmSchedules { get; set; }
public virtual List<Equipment>? Equipments { get; set; }
public virtual List<User>? Users { get; set; }
}

我的上下文类:

protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}

我在更新数据库时收到以下错误:

引入FOREIGN KEY约束"PmDataSets"表上的"FK_PmDataSet_Equipments_EquipmentId"可能导致循环或多个级联路径。指定ON DELETE NO ACTION或ONUPDATE NO ACTION,或修改其他FOREIGN KEY约束。无法创建约束或索引。请参阅以前的错误。

您需要添加一些额外的配置,如下所示:

protected override void OnModelCreating(ModelBuilder mb)
{   
var pmConfig = mb.Entity<PmDataSet>();
pmConfig.HasOne(n => n.Equipment).WithMany(n => n.PmDataSets).OnDelete(DeleteBehavior.NoAction);
}

问题是您的设备型号或/和其他一些型号已经具有至少一个级联删除关系,因此,如果添加另一个级联删除关系,那么如果其中一个实体被删除,就会出现链式删除。因此,您需要告诉ef,在删除时,这些关系中的一些/没有级联。

(A) <--级联-->(B)

(B) <--级联-->(C)所以在a和C之间会有一个逻辑级联,这不是任意的。

只要稍微玩一下这个配置,你就会解决你的问题;)

--------更新要回答评论的问题,你可以通过ef定罪:

public User MainUploader { get; set; }
[Required]
public int MainUploaderId { get; set; }
public User Uploader { get; set; }
public int? UploaderId { get; set; }

如果您想使用另一种命名属性的方式,也可以使用[ForeignKey("fkName")]注释,或者使用fluent API ForeignKey(a=>a.something)方法或其重载。

相关内容

  • 没有找到相关文章

最新更新