Как перезагрузить сущность в EntityFramework? - PullRequest
0 голосов
/ 21 января 2020

У меня есть классы:

public class abstract Person{
    public int Id{set;get;}
    public string Name {set;get;}
}

public class Student:Person{
    public string Specialisation {set;get;}
}

public class Instructor:Person{
   public decimal Salary {set;get;}
}

В базе данных у меня есть таблицы: люди, студенты, преподаватели для этих классов.

Теперь в моем приложении я хочу изменить одного из студентов на instrector. Я имею в виду, что мне нужно изменить тип объекта, но мне нужно сохранить тот же Id. Я не нашел, как это сделать с EF, поэтому я просто использую скрипт SQL:

using (var command = db.Database.Connection.CreateCommand())
            {
                if (command.Connection.State == ConnectionState.Closed) command.Connection.Open();

                if (db.Database.CurrentTransaction != null)
                    command.Transaction = db.Database.CurrentTransaction.UnderlyingTransaction;

                command.CommandText = $@"delete from [dbo].[Students] where Id = @id;
                                        insert into [dbo].[Instructors](Id) values(@id)";

                command.Parameters.Add(new SqlParameter("@id", SqlDbType.Int) { Value = myId });
                command.ExecuteNonQuery();
            }

Но когда я попытался получить этот новый Инструктор в том же контексте, я получил ошибку:

   var instructor = db.Instructors.FirstOrDefault(t=>t.Id = myId);

   All objects in the EntitySet 'myContext.Person' must have unique primary keys. However, an instance of type 'Person.Instructor' and an instance of type 'Person.Student' both have the same primary key value, 'EntitySet=Person;Id=1'. 

Я попытался перезагрузить базовый объект:

var myPerson = db.Persons.FirstOrDefault(t=>t.Id = myId);

///
my sql where i delete Student and insert Instructor
///

db.Entry(myPerson).Reload();

var instructor = db.Instructors.FirstOrDefault(t=>t.Id = myId);

Но получил ту же ошибку. Так как сделать это правильно?
Я имею в виду, может быть, мое решение совершенно неверно? Или если нет, то как я могу перезагрузить сущность?

1 Ответ

0 голосов
/ 22 января 2020

Подойдет мем Боромира Шона Бина, в котором говорится: «Человек не просто меняет тип сущности». Когда дело доходит до наследования на простом уровне, Собака и Кошка могут наследовать от Животного, но Собака никогда не становится Кошкой.

Человек - это сущность. То, что они делают, это Роль, а не сущность, или, если это сущность, она может быть связана с этим человеком.

Например, используя Персона, Инструктор, Студент, Курс:

На курсе есть инструктор и студенты. Если студенты и преподаватели расширяют Person, то PK ученика - это PersonId, а PK инструктора - это PersonID. Моя структура таблицы может выглядеть примерно так:

Person [PersonId, Name, ... общие поля]

Instructor [PersonId, .. поля преподавателя]

Студент [PersonId, ... поля ученика]

Курс [CourseId, InstructorPersonId, Имя, ... курс поля]

CourseStudent [CourseId, StudentPersonId]

В качестве альтернативы схема Person / Student / Instructor может быть:

Person [PersonId, Role, Name, ...]

Где Role - это дискриминатор, который EF может использовать для разграничения наследования инструктора и ученика. В любом случае, это не очень хорошая модель, потому что она гарантирует, что преподаватель курса на самом деле указывает на человека, связанного со строкой преподавателя? Если бы вы просто удалили строку инструктора, чтобы человек мог сделать его студентом, курс все равно мог бы рассматривать их в качестве инструктора.

Вместо этого вам следует подумать об ассоциации. Люди не меняются, просто меняются их роли. Каждому курсу нужен инструктор, и в нем будут студенты, и, вероятно, будут детали, которые указаны c для этого инструктора (квалификации) и студентов. (оценки)

Person [PersonId, Name, ...]

Role [RoleId, Name] // Т.е. "Инструктор"

PersonRole [PersonId, RoleId]

Instructor [InstructorId, PersonId, ...] // Подумайте о «позиции преподавателя»

Student [StudentId, PersonId ...] // Можно рассматривать как «место для учащихся»

Course [CourseId, InstructorId, Имя, ...]

StudentCourse [StudentId, CourseId]

В этом случае Инструктор и Студент не наследуют от Person, они связаны с человеком , Человек может иметь ассоциации с ролями, которые могут учитываться, когда человек может быть связан с должностью инструктора или нет. Приложению по-прежнему необходимо будет регулировать правила, касающиеся ассоциаций, например, если должность преподавателя заполняется другим человеком, и чтобы в курсе не было одного и того же «человека», выступающего в роли преподавателя и студента, и что места для студентов не поменять людей. (оценки не переносятся)

Таким образом, вы можете создавать / управлять преподавателями и студентами независимо от тех, кто за ними стоит. «Студент» как сущность совершенно необязателен, вместо этого CourseStudent может просто связать PersonId, а такие вещи, как оценки, могут быть связаны непосредственно с Person. Тот факт, что человек, который был студентом и имел, например, оценки, зарабатывает роль преподавателя и может быть связан с позицией преподавателя для курса, ничего не нарушает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...