EF4代码只有TPH更改对象类型

时间:2010-08-18 22:53:50

标签: entity-framework-4 code-first

我正在尝试使用EF4 Code Only来解决问题。如果我使用TPH并且我想将保存的人员更改为教师,反之亦然,我将如何实现这一目标。我的POCO课程:

    public class Person
{
    public int PersonId { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }
}
public class Instructor : Person
{
    public DateTime? HireDate { get; set; }
}

public class Student : Person
{
    public DateTime? EnrollmentDate { get; set; }
}

public class Admin : Person
{
    public DateTime? AdminDate { get; set; }
}

public class PersonConfiguration : EntityConfiguration<Person>
{
    public PersonConfiguration()
    {
        this.HasKey(u => u.PersonId).Property(u => u.PersonId).IsIdentity();
        MapHierarchy()
            .Case<Person>(p => new
            {
                p.PersonId,
                p.FirstName,
                p.LastName,                    
                PersonCategory = 0
            })
            .Case<Instructor>(i => new
            {

                i.HireDate,
                PersonCategory = 1
            })
            .Case<Student>(s => new
            {
                s.EnrollmentDate,
                PersonCategory = 2
            })
            .Case<Admin>(a => new
            {

                a.AdminDate,
                PersonCategory = 3
            }).ToTable("Person");

    }
}

假设我有一个人:

var person1 = new Person { FirstName = "Bayram", LastName = "Celik" };
context.People.Add(person1);
context.SaveChanges();

后来我想让这个人成为管理员。我将如何实现这一目标。

var person = context.People.FirstOrDefault();
Admin test = person as Admin; // wont work

以下将更改HireDate列,但我的鉴别器字段PersonCategory仍为0.因此,就EF关注而言,它仍然不是管理员类型

Admin admin = new Admin();
admin.PersonId = person.PersonId;
admin.AdminDate = DateTime.Now;

context.ObjectContext.Detach(person);
context.People.Attach(admin);
var customerEntry = context.ObjectContext.ObjectStateManager.GetObjectStateEntry(admin);
customerEntry.SetModified();
customerEntry.SetModifiedProperty("AdminDate");

1 个答案:

答案 0 :(得分:2)

您无法更改对象的类型。您无法在C#中执行此操作,并且EF无法解决此问题。这是OOP的基本原则。

相反,您需要修复模型设计。 As I wrote a while back

  

在设计良好的对象关系映射时,您必须克服的一个心理障碍是倾向于主要以面向对象的术语或关系术语来思考,以适合您的个性。但是,良好的对象关系映射包含了良好的对象模型和良好的关系模型。例如,假设您有一个包含People表的数据库,以及Employees和Customers的相关表。一个人可能在所有三个表中都有记录。现在,从严格的关系角度来看,您可以为员工构建数据库VIEW,为客户构建另一个数据库VIEW,这两者都包含People表中的信息。当使用一个VIEW或另一个时,您可以暂时将个人视为“只是”员工或“只是”客户,即使您知道他们两者都是。所以来自这个世界观的人可能会想要进行OO映射,其中Employee和Customer都是Person的(直接)子类。但这不适用于我们拥有的数据;由于单个人同时拥有员工和客户记录(并且由于任何Person实例都不能同时具有子类型Employee和Customer),因此Person和Employee之间的OO关系需要是组合而不是继承,对于Person和Customer也是如此。