实体框架朝向两个表的一个外键-代码优先

时间:2019-01-30 14:23:33

标签: entity-framework entity-framework-6

全部, 是否可以对两个表使用相同的FK。 可能这不是一个好习惯,但是我可以预订两个不同的课程:

public class Course {

    public Course() {
        BookingRefs = new HashSet<BookingRef>();
    }

    public long Id { get; set; }
    public string Title { get; set; }
    // other props ...

    [InverseProperty(nameof(BookingRef.Course))]
    public virtual ICollection<BookingRef> BookingRefs { get; set; }
}

public class GiftCard {

    public GiftCard() {
        BookingRefs = new HashSet<BookingRef>();
    }

    public long Id { get; set; }
    public string Prop1 { get; set; }
    public int Prop2 { get; set; }
    // other props ...

    [InverseProperty(nameof(BookingRef.Course))]
    public virtual ICollection<BookingRef> BookingRefs { get; set; }
}

// this is the bookin reference for a Course or an GiftCard
public class BookingRef {

    public BookingRef() {
    }

    public long Id { get; set; }
    // other props ...

    /// <summary>The item (usually the course but theoretically anything with a long id)</summary>
    public long? ItemId { get; set; }

    // maybe a generic Object?
    [ForeignKey(nameof(ItemId))]
    public Object GiftCard { get; set; }

    // maybe 2 items possibly null?
    [ForeignKey(nameof(ItemId))]
    public Course Course { get; set; }

    // maybe 2 items possibly null?
    [ForeignKey(nameof(ItemId))]
    public GiftCard GiftCard { get; set; }
}

2 个答案:

答案 0 :(得分:0)

  

是否可以对两个表使用相同的FK

不。关系模型不允许这样做。您可以引入所有可预订商品的超类,并为此设置一个FK,但您不应该仅凭一个收藏而不是多个收藏就可以做到这一点。

答案 1 :(得分:0)

从关系数据的角度考虑。数据库将如何知道“项目ID”指向的表?它会如何编制索引?

在预订中的每个相关表上使用可为空的FK就是这种情况。这些FK不需要驻留在实体中,只需驻留在导航属性中即可。您可以在EF6中利用.Map(x => x.MapKey)或在EF Core中利用.HasForeignKey("")来利用阴影属性。

如果您只希望将预订仅与课程或礼品卡相关联,而不与两者相关联,则这不会强制执行。这需要在应用程序级别解决,我建议使用计划的维护任务来评估数据是否违反该规则。 (例如,查找同时包含课程ID和礼品卡ID的预订)

您也可以选择使连接保持“松散”状态,并由应用程序根据类似于继承模型的区分符进行评估。 (ItemId + ItemType)但是,您必须基于ItemType分别解决应用程序中的关系负载,并且丢失数据库中的所有FK,索引和数据完整性检查。要节省添加几个FK,这可能是一笔巨大的性能和维护成本。