我有一个基本的继承层次结构,如下所示:
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 回答
根据您的描述我有点困惑,但会尝试回答我认为您可能意味着的情景:
Option 1 :我认为这就是你所追求的:你正在创建父类的对象 . 稍后,您有更多信息,并希望'downcast'它们到相应的子类 . 用EF这种方式是不可能的 . 一旦将对象创建为必须保留的特定类型 . 在您的情况下,选项如下:
此对象是否已存在(parentType)
删除对象(ParentType)
保存对象(ChildType)
看到比我在这里给出的措辞更好的解释:
Add child to existing parent record in entity framework
Downcasting with Entity Framework
如果这是您打算做的,我会建议重新考虑正在实施的模型的某些部分以避免这些情况 .
Option 2 :您有一个子元素列表,它们属于父对象的一个组(在这种情况下是超类型):
在这些情况下,您可以加载父项,将子项添加到父项,然后保存(在父级别):
UPDATE: Option 3
基于您对共享父ID的评论:您现在谈论的不是TPT实施,而是您在此处违反规则 . 在TPT中,您有一个ID,它位于'parent'表中,该表是每个对象的所有表的主键 . 永远不应该存在两个子对象(任何类型)具有相同主键的情况,并且在所有情况下都是子对象主键 IS parentID . 使用较少抽象的术语可能有助于消除混淆:如果父表是动物而子表是猫和狗,很明显猫和狗不会共享主键(因为它们是不同的类型 . 我想你可能是什么尝试实现可能是相反的:一个Child应该包含一个父实例(使用你问题中的术语) .
再说一遍,如果parentID是主键,它将只存在于对象层次结构的一个分支中,并且只用于将构成该对象的继承链拉在一起 . 例如,如果我有一个像这样的层次结构
动物 - > Dog->贵宾犬
我创建了一个ID为1的新贵宾犬,我只会有一组ID为1的记录,并且每个动物,狗和贵宾犬都会有一行 . (这三个记录都是针对同一个Poodle对象的),