使用继承时设置外键关联的正确方法

本文关键字:关联 方法 继承 设置 | 更新日期: 2023-09-27 18:16:39

我的数据库中有两个表:MastersDetails
这些表是一对多的,有一个外键约束,其中Masters是一个主键表,Details是一个外键表。

我想在我的模型中使用继承从Masters表的实体:

abstract class Master
{
    public int Id { get; set; }
}
class Master_1 : Master
{
    // other properties
}
class Master_2: Master
{
    // other properties
}

对于Details表中的实体:

abstract class Detail
{
    public int Id { get; set; }
}
class Detail_1 : Detail
{
    // other properties
}
class Detail_2: Detail
{
    // other properties
}
class Detail_3: Detail
{
    // other properties
}

但是外键呢?
从概念上讲,Master_1应该只包含Detail_1的细节,而Master_2应该包含Detail_2Detail_3的细节。

如果我要从实体框架中抽象,我会为Detail_2Detail_3添加中间基类:

   abstract class Detail_2_Or_3 : Detail {}
   class Detail_2 : Detail_2_Or_3 {}
   class Detail_3 : Detail_2_Or_3 {}

并使我的Master通用:

abstract class Master<TDetail>
    where TDetail : Detail
{
    public int Id { get; set; }
    public Collection<TDetail> Details { get; private set; }
}
class Master_1 : Master<Detail_1> {}
class Master_2 : Master<Detail_2_Or_3> {}

但是如何使用实体框架来实现呢?当MasterDetails的集合时,我不喜欢这个解决方案,因为这不能提供编译时保证。

我正在寻找在MasterDetail层次结构上没有额外层的方法。什么好主意吗?

使用继承时设置外键关联的正确方法

这只是一个想法,我还没有在EF中完全尝试过,但是…

为什么不像你说的那样设置事情,并在你的域对象上使用一组限制性的公共方法来提供编译时安全?

也就是说,Master是在EF中使用Details的集合建立的,但是你只能将Detail_1的实例添加到Master_1的实例中等等。然后,您可以使用返回适合基类型的强类型集合的方法。

代码如下:

public abstract class Master<TDetail> where TDetail : Detail
{
    public int Id { get; set; }
    public List<Detail> Details { get; private set; }
    public abstract void AddDetail(TDetail detail);
    public abstract List<TDetail> GetDetails();
}
public class Master_1 : Master<Detail_1> 
{
    public override void AddDetail(Detail_1 detail) 
    {
        Details.Add(detail);
    }
    public override List<Detail_1> GetDetails()
    {
        return Details.Select(d => (Detail_1)d).ToList();
    }
}
public class Master_2 : Master<Detail_2_Or_3> 
{
    public override void AddDetail(Detail_2_Or_3 detail)
    {
        Details.Add(detail);
    }
    public override List<Detail_2_Or_3> GetDetails()
    {
        return Details.Select(d => (Detail_2_Or_3)d).ToList();
    }
}
public abstract class Detail
{
    public int Id { get; set; }
    //Foriegn Key
    public int MasterId { get; private set;}
}
public class Detail_1 : Detail { }
public abstract class Detail_2_Or_3 : Detail { }
public class Detail_2 : Detail_2_Or_3 { }
public class Detail_3 : Detail_2_Or_3 { }