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

时间:2013-06-03 09:24:30

标签: c# entity-framework ef-code-first

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

我想在我的模型中为Masters table:

中的实体使用继承
abstract class Master
{
    public int Id { get; set; }
}

class Master_1 : Master
{
    // other properties
}

class Master_2: Master
{
    // other properties
}

以及来自Details table的实体:

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> {}

但是如何使用Entity Framework实现这一目标?当Master有一个Details的集合时,我不喜欢这个解决方案,因为这不能提供编译时保证。

我正在寻找没有MasterDetail层次结构的额外图层的方法。 有什么想法吗?

1 个答案:

答案 0 :(得分:0)

这只是一个想法,我没有用EF完全尝试过,但是......

为什么不像你说的那样进行设置,并为你的域对象提供一组限制性公共方法的编译时安全性?

也就是说,Master在EF中设置了一组Details,但是你只能将一个Detail_1实例添加到Master_1等实例中。然后你可以有一个方法返回一个适合于base的强类型集合。也是类型。

以下是代码:

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 { }