我在插入继承自基类的子类实例时遇到问题。
请考虑以下来自这些POCO的代码片段:
public abstract class EntityBase<T>
{
private T _id;
[Key]
public T ID
{
// get and set details ommitted.
}
}
public abstract class PersonBase<T> : EntityBase<T>
{
// Details ommited.
}
public class Applicant : PersonBase<int>
{
// Details ommitted for brevity.
}
public class Employee : Applicant {}
现在很标准的继承。在我们的系统中,当申请人最终成为雇员时,我们会收集额外的数据。如果没有被录用,他们仍然是申请人,信息有限。
现在考虑使用流畅的API来设置每个类型的表继承模型:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Set up table per type object mapping for the Visitor Hierarchy.
modelBuilder.Entity<Employee>().ToTable("Employees");
}
到目前为止,非常好......
如果我查看这个创建的数据库,我有一个名为Applicants的表,其Id类型为int,自动递增ID,我有一个Employees表,其中ID字段作为主键(非自动递增)。
基本上,Employees表中的ID字段是Applicants表的外键。
这就是我想要的。在实际成为Employee之前,我不希望记录到与Applicants表对应的Employees表中。
当我尝试插入一个归结为此代码的Employee时出现问题:
public void PersistCreationOf(T entity)
{
DataContextFactory.GetDataContext().Set(typeof(T)).Add(entity);
}
问题:它插入了一个全新的申请人和员工。我把它连接到Sql Profiler并查看了两个插入查询。
我想只使用已有的ID(Visitors表中的外键)插入Employee记录。
我理解默认情况下它需要:显然如果你创建一个子类并插入它,它需要插入到两个表中。
我的问题是可以告诉框架 - 基表已经有信息 - 只需插入子表?
提前致谢!
答案 0 :(得分:0)
除了发送原始SQL命令以将Employee
减去Applicant
属性片段插入Employees
表之外,我认为这是不可能的。您可以更新或插入实体。你想要的基本上是更新Employee
的基础部分(如果没有改变则不做任何事情)并插入不可能的派生部分。
想象一下ORM的作用:它将数据库中的关键标识映射到内存中的对象标识。即使在内存中你也无法达到你想要的效果:如果你的内存中有一个是 Applicant
的对象,它总是一个申请者。你不能神奇地将它“升级”为Employee
。您必须创建Employee
类型的新对象,将Applicant
的属性复制到新Employee
的基本属性中,然后删除Applicant
。结果是一个具有新对象标识的新对象。
我认为你必须在EF中遵循相同的程序。您的Employee
将是一个新实体,在Applicant
和Employee
表中都有新行,您需要删除旧的Applicant
。如果您有自动生成的密钥,它将是具有新ID的新标识。 (如果您没有自动生成密钥,则可以在删除旧Applicant
后再次提供旧ID,从而“伪造”未更改的身份。)如果您引用旧申请人,这当然会产生很大的潜在问题有FK约束。
对于将申请人“升级”为员工的情况,或许继承并不是最佳选择。 Applicant
内部的可选导航属性(1对0 ... 1关系)指的是包含使申请人成为雇员的附加属性的另一个实体将解决问题。可以设置或不设置此导航属性,让您区分申请人和也是员工的申请人。当你成为一名雇员时,你不需要删除和更改申请人的身份证。
(如上所述,“我相信”。也许有一种隐藏的方式,我没有看到。)