同一实体的外键,一个是必需的,另一个是可选的

Foreign keys to same Entity with one required and another optional

我正在尝试如下创建两个实体并使用 Fluent API 向它们添加引用约束。

它的设计是为了强制执行必需的主要联系人和可选的次要联系人,并增加了主要和次要联系人可能指的是 ContactInfo 实体中的两个不同联系人的要求。

public class Employee
{
    public int EmployeeId { get; set; }

    public int PrimaryContactId { get; set; }
    public int SecondaryContactId { get; set; }

    public virtual ContactInfo PrimaryContact { get; set; }
    public virtual ContactInfo SecondaryContact { get; set; }
}

public class ContactInfo
{
    public int ContactId { get; set; }
    public string PhoneNumer { get; set; }
    public string Email { get; set; }
}

public class EmployeeConfiguration : EntityTypeConfiguration<Employee>
{
    public EmployeeConfiguration ()
    {
        var employeeEntity = this;

        employeeEntity.HasKey(e => e.EmployeeId).ToTable("Employees");
        employeeEntity.Property(e => e.EmployeeId).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity);

        employeeEntity.HasRequired(e => e.PrimaryContact).WithMany().HasForeignKey(e => e.PrimaryContactId).WillCascadeOnDelete(true);
        employeeEntity.HasRequired(e => e.SecondaryContact ).WithMany().HasForeignKey(e => e.SecondaryContact Id).WillCascadeOnDelete(false);
    }
}

它似乎按预期创建了所需的约束,但是当我尝试添加一个将 SecondaryContact 设置为 null 的员工时,为这个新员工创建的行将 SecondaryContactId 设置为与 PrimaryContactId 相同,这不是我的意图。

我一开始就无法理解设计是否正确,或者需要调整配置才能获得正确的结果。

您可以添加外键注释,如果您希望键为空,也可以将键设置为可为空。

public class Employee
{
    public int EmployeeId { get; set; }

    public int? PrimaryContactId { get; set; }
    public int? SecondaryContactId { get; set; }

    [ForeignKey("PrimaryContactId")]
    public virtual ContactInfo PrimaryContact { get; set; }
    [ForeignKey("SecondaryContactId")]
    public virtual ContactInfo SecondaryContact { get; set; }
}

将辅助联系人 ID 设置为可为 null 的类型。

public int? SecondaryContactId { get; set; }

您似乎将这两个联系人都设置为您的员工对象需要。 如果你想要 SecondaryContract 可选更改:

employeeEntity
    .HasRequired(e => e.SecondaryContact)
    .WithMany()
    .HasForeignKey(e => e.SecondaryContactId)
    .WillCascadeOnDelete(false);

employeeEntity
    .HasOptional(e => e.SecondaryContact)
    .WithMany()
    .HasForeignKey(e => e.SecondaryContactId)
    .WillCascadeOnDelete(false);

另外更改:

public int SecondaryContactId { get; set; }

public int? SecondaryContactId { get; set; }

因为您的 SecondaryContactId 是可选的。