首页 文章

代码优先TPT继承 - 如何提供外键而不是EF为我创建父行?

提问于
浏览
1

我有一个基本的继承层次结构,如下所示:

public class Parent
{
    public int ParentID {get; set;}

    public string SomeOtherProperty {get; set;}
};

public class Child : Parent
{
    public string SomeChildProperty {get; set;}
};

我有多个子类,我有一个Auditor对象,它有一个基于Parent类的接口,允许我以通用的方式写入数据库,就像这样

public class Auditor
{
    public void WriteObject(Parent p)
    {
        using (MyDbContext context = new Context)
        {
            context.Parents.Add(p);
            context.SaveChanges();
        }
    }
}

所以我可以使用Auditor

auditor.WriteObject(new Child1());
auditor.WriteObject(new Child2());

等等,每当我写一个Child对象时,EF就为我在DB中创建了Parent行 .

我遇到的问题是在某些情况下(可能是10%的时间),我想将一条子记录写入数据库并将其链接到现有的父行,即我想提供外键 .

我试过类似的东西

Child1 child = new Child();
child1.ParentID = existingID;
auditor.WriteObject(child);

但EF忽略了我提供的外键并为我创建了一个新的父记录 .

反正有没有让EF理解这一点,因为父ID已经存在于我正在尝试编写的Child对象上,它不需要插入父行?

1 回答

  • 3

    根据您的描述我有点困惑,但会尝试回答我认为您可能意味着的情景:

    Option 1 :我认为这就是你所追求的:你正在创建父类的对象 . 稍后,您有更多信息,并希望'downcast'它们到相应的子类 . 用EF这种方式是不可能的 . 一旦将对象创建为必须保留的特定类型 . 在您的情况下,选项如下:

    • 此对象是否已存在(parentType)

    • 删除对象(ParentType)

    • 保存对象(ChildType)

    看到比我在这里给出的措辞更好的解释:

    Add child to existing parent record in entity framework

    Downcasting with Entity Framework

    如果这是您打算做的,我会建议重新考虑正在实施的模型的某些部分以避免这些情况 .

    Option 2 :您有一个子元素列表,它们属于父对象的一个组(在这种情况下是超类型):

    在这些情况下,您可以加载父项,将子项添加到父项,然后保存(在父级别):

    Child1 child = new Child();
    Parent p = _context.Parents.Find(search based on ID)
    p.Children.Add(child);
    auditor.WriteObject(p);
    

    UPDATE: Option 3

    基于您对共享父ID的评论:您现在谈论的不是TPT实施,而是您在此处违反规则 . 在TPT中,您有一个ID,它位于'parent'表中,该表是每个对象的所有表的主键 . 永远不应该存在两个子对象(任何类型)具有相同主键的情况,并且在所有情况下都是子对象主键 IS parentID . 使用较少抽象的术语可能有助于消除混淆:如果父表是动物而子表是猫和狗,很明显猫和狗不会共享主键(因为它们是不同的类型 . 我想你可能是什么尝试实现可能是相反的:一个Child应该包含一个父实例(使用你问题中的术语) .

    再说一遍,如果parentID是主键,它将只存在于对象层次结构的一个分支中,并且只用于将构成该对象的继承链拉在一起 . 例如,如果我有一个像这样的层次结构

    动物 - > Dog->贵宾犬

    我创建了一个ID为1的新贵宾犬,我只会有一组ID为1的记录,并且每个动物,狗和贵宾犬都会有一行 . (这三个记录都是针对同一个Poodle对象的),

相关问题