Код EF4 только TPH изменить тип объекта - PullRequest
0 голосов
/ 19 августа 2010

Я пытаюсь что-то выяснить с помощью 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. Таким образом, это не относится к типу Admin, если говорить о 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 Ответ

2 голосов
/ 19 августа 2010

Вы никогда не сможете изменить тип объекта. Вы не можете сделать это в C #, и EF не работает вокруг этого. Это фундаментальный принцип ООП.

Вместо этого вам нужно исправить дизайн вашей модели. Как я писал некоторое время назад :

Одним из ментальных барьеров, которые вам приходится преодолевать при разработке хорошего объектного реляционного отображения, является склонность мыслить в первую очередь в объектно-ориентированных терминах или в реляционных терминах, в зависимости от того, что подходит вашей личности. Хорошее объектное реляционное отображение, тем не менее, включает в себя как хорошую объектную модель, так и хорошую реляционную модель. Например, допустим, у вас есть база данных с таблицей для сотрудников и связанными таблицами для сотрудников и клиентов. Один человек может иметь запись во всех трех таблицах. Теперь, с строго реляционной точки зрения, вы можете создать базу данных VIEW для сотрудников и другую для клиентов, которые содержат информацию из таблицы People. При использовании одного или другого ПРОСМОТРА вы можете временно думать об отдельном человеке как о «просто» сотруднике или «просто» клиенте, даже если вы знаете, что они оба. Таким образом, у кого-то из этого мировоззрения может возникнуть соблазн сделать OO-отображение, где Employee и Customer являются (прямыми) подклассами Person. Но это не работает с данными, которые у нас есть; поскольку у одного лица есть записи как о сотруднике, так и о клиенте (и поскольку ни один экземпляр Person не может одновременно иметь конкретный подтип Employee и Customer), отношение OO между Person и Employee должно быть составным, а не наследованием, и аналогично для Person и Customer.

...