【问题标题】:The proper way to setup foreign key association when using inheritance使用继承时设置外键关联的正确方法
【发布时间】:2013-06-03 09:24:29
【问题描述】:

我的数据库中有两个表: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> {}

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

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

【问题讨论】:

  • 这是一本有趣的读物,希望能为您提供深思...weblogs.asp.net/manavi/archive/2011/01/03/…
  • @PaulZahra:我认为 TPC 继承的描述没有帮助。可能是我遗漏了什么?
  • 你看TPT和TPH了吗?
  • 问题不在于选择继承模型(在这种特殊情况下将是 TPT)。问题是关于如何配置关系,因此它将提供编译时安全性。
  • 对于抽象类,关联必须仅引用其子类之一的实例。

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


【解决方案1】:

这只是一个想法,我还没有用 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 { }  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-06
    • 1970-01-01
    • 2012-04-11
    • 1970-01-01
    • 2019-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多