实体框架代码优先 - 每种类型的表继承 - 插入问题?

时间:2011-06-15 13:55:01

标签: entity-framework code-first

我在插入继承自基类的子类实例时遇到问题。

请考虑以下来自这些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字段是App​​licants表的外键。

这就是我想要的。在实际成为Employee之前,我不希望记录到与Applicants表对应的Employees表中。

当我尝试插入一个归结为此代码的Employee时出现问题:

public void PersistCreationOf(T entity)
{     
    DataContextFactory.GetDataContext().Set(typeof(T)).Add(entity);
} 

问题:它插入了一个全新的申请人和员工。我把它连接到Sql Profiler并查看了两个插入查询。

我想只使用已有的ID(Visitors表中的外键)插入Employee记录。

我理解默认情况下它需要:显然如果你创建一个子类并插入它,它需要插入到两个表中。

我的问题是可以告诉框架 - 基表已经有信息 - 只需插入子表?

提前致谢!

1 个答案:

答案 0 :(得分:0)

除了发送原始SQL命令以将Employee减去Applicant属性片段插入Employees表之外,我认为这是不可能的。您可以更新或插入实体。你想要的基本上是更新Employee的基础部分(如果没有改变则不做任何事情)并插入不可能的派生部分。

想象一下ORM的作用:它将数据库中的关键标识映射到内存中的对象标识。即使在内存中你也无法达到你想要的效果:如果你的内存中有一个 Applicant的对象,它总是一个申请者。你不能神奇地将它“升级”为Employee。您必须创建Employee类型的新对象,将Applicant的属性复制到新Employee的基本属性中,然后删除Applicant。结果是一个具有新对象标识的新对象。

我认为你必须在EF中遵循相同的程序。您的Employee将是一个新实体,在ApplicantEmployee表中都有新行,您需要删除旧的Applicant。如果您有自动生成的密钥,它将是具有新ID的新标识。 (如果您没有自动生成密钥,则可以在删除旧Applicant后再次提供旧ID,从而“伪造”未更改的身份。)如果您引用旧申请人,这当然会产生很大的潜在问题有FK约束。

对于将申请人“升级”为员工的情况,或许继承并不是最佳选择。 Applicant内部的可选导航属性(1对0 ... 1关系)指的是包含使申请人成为雇员的附加属性的另一个实体将解决问题。可以设置或不设置此导航属性,让您区分申请人和也是员工的申请人。当你成为一名雇员时,你不需要删除和更改申请人的身份证。

(如上所述,“我相信”。也许有一种隐藏的方式,我没有看到。)