繁体   English   中英

如何在 EntityFramework 中重新加载实体?

[英]How to reload entity in EntityFramework?

我有一个课程:

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;}
}

在数据库中,我有表格:本课程的人员、学生、教师。

现在在我的应用程序中,我想将其中一名学生更改为讲师。 我的意思是我需要更改实体类型但我需要保存相同的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();
            }

但是当我试图在相同的上下文中获取这个新 Instructor 时,我得到了错误:

   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);

但是得到了同样的错误。 那么如何正确地做到这一点呢?
我的意思是也许我的解决方案完全错误? 或者,如果不是,我该如何重新加载实体?

肖恩·宾 (Sean Bean) 的博罗米尔 (Boromir) 的一个模因说“一个人不会简单地改变一个实体的类型”是合适的。 当涉及到简单级别的继承时,狗和猫可以从动物继承,但狗永远不会成为猫。

一个人是一个实体。 他们所做的是角色,而不是实体,或者如果它是实体,它可以与那个人相关联。

例如,使用 Person、Instructor、Student、Course:

课程有教师和学生。 如果学生和教师扩展 Person,那么学生的 PK 是 PersonId,而教师的 PK 是 PersonID。 我的表结构可能类似于:

Person [PersonId, Name, ... 公共字段]

讲师[PersonId, ... 讲师字段]

学生[PersonId, ... 学生字段]

课程[CourseId, InstructorPersonId, Name, ... 课程字段]

CourseStudent [CourseId, StudentPersonId]

或者,Person/Student/Instructor 模式可以是:

[PersonId, Role, Name, ...]

其中 Role 是 EF 可以用来区分 Instructor 和 Student 继承的鉴别器。 无论哪种方式,它本质上都不是一个好的模型,因为什么可以确保课程的讲师实际上指向与 Instructor 行相关联的 Person? 如果您只是删除一个人的讲师行以使他们成为学生,课程仍然可以将他们视为讲师。

相反,您应该考虑关联。 人不会变,只是角色变了。 每门课程都需要一位讲师,并且会有学生,并且可能会有针对该讲师(资格)和学生的详细信息。 (成绩)

[PersonId, 姓名, ...]

Role [RoleId, Name] // 即“讲师”

PersonRole [PersonId, RoleId]

讲师[InstructorId, PersonId, ...] // 认为是“讲师职位”

Student [StudentId, PersonId...] // 可以认为是一个“Student Spot”

课程[CourseId, InstructorId, Name, ...]

学生课程 [StudentId, CourseId ]

在这种情况下,Instructor 和 Student 不是从 Person 继承的,而是与一个人关联的。 一个人可以持有与角色的关联,当一个人可以与讲师职位关联或不关联时,可以考虑这些关联。 该应用程序仍需要规范有关关联的规则,例如教师职位是否由另一个人填补,并确保课程中不会有同一“人”担任教师和学生,并且学生名额不会换人。 (成绩不转移)

通过这种方式,您可以独立于他们背后的人来创建/管理教师和学生。 “Student”作为一个实体是完全可选的,CourseStudent 可以只关联 PersonId,而成绩之类的东西可以直接关联到 Person。 例如,一个曾经是学生并且有成绩的人获得了讲师的角色并且可以与课程的讲师职位相关联这一事实并没有破坏任何东西。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM