inheritance - 首先在实体框架代码中转换为派生类型
问题描述
我在 MVC C# 中使用 EntityFramework 6,代码优先。我有几个看起来像这样的简单实体:
public class Person {
public int Id { get; set; }
public string FirstName {get; set;}
public string LastName {get;set;}
public string EmailAddress { get; set; }
}
public class Employee : Person {
public DateTime DateStarted { get; set; }
public ICollection<Roles> Roles { get; set; }
}
你明白了。我遇到的问题是当数据库中的现有人员成为员工时。所以我已经有一个与他们关联的 Person 记录,但现在他们已经成为员工,所以现在他们需要一个 Employee 记录。我看不到任何方法可以用 EF 做到这一点。我希望能够做的事情如下:
Person person = GetPerson();
Employee employee = (employee)person;
context.Employees.Add(employee);
SaveChanges();
但是 C# 不允许你将基类型转换为子类型,所以我不能这样做,如果我创建一个新的 Employee 记录,那么 Entity 框架也会创建一个新的 Person 记录。有谁知道实现这一目标的简单方法?我认为设计是正确的,因为 Employee是一个Person,所以在这种情况下,对组合的继承肯定是正确的选择。
我可以自己编写一些 SQL 来将我需要的记录插入到 Employee 表中,或者我可以删除旧记录并用新记录替换它(这会带来一大堆外键问题),但如果我这样做我接受 Entity Framework 基本上让我失望了一个非常简单和常见的要求。有没有办法解决这个问题?
提前感谢您的任何答案。
解决方案
您的问题的原因是表格及其列对您来说并不是很清楚。
数据库中的每个对象都有一个用于标识对象属性的主键。对象的属性可能会改变,对象所代表的事物将是相同的事物。
一个人可能会改变他的地址,他甚至可能改变他的名字、性别或生日,因为数据库仍然是同一个人。只有你改变他的Id,它才真正成为一个不同的人。
显然你有Persons
那还不是一个Employee
. 如果Person
开始为你工作,这是否意味着他变得与众不同Person
?他的身份应该改变吗?
您可以决定,如果Person
ID 为 10Employee
的对象变为 ,则创建Employee
ID 为 10 的对象,如果这Person
也变为对象,则Customer
创建Customer
ID 为 10 的对象。如果Employee
停止为您工作,则删除Employee
ID 为 10 的对象并保留和ID 为 10 Person
。Customer
尽管这可行,但它需要您自己进行 ID 编号。数据库很难检查你是否做了非法的事情,比如杀死一个Person
仍然是你的Employees
.
与其使用一个 ID 来识别 your Employee
、 yourPerson
和 your Customer
,不如给它们自己的主键。给Employee
他们Customer
一个外键Person
。事实上, Person 更像是PersonData
. 员工不是个人,员工有个人数据
class PersonData // your old Person
{
public int Id {get; set;}
...
}
class Employee
{
public int Id {get; set;}
// every Employee has PersonData using foreign key
public int PersonDataId {get; set;}
public virtual PersonData PersonData {get; set;}
...
}
class Customer
{
public int Id {get; set;}
// every Customerhas PersonData using foreign key
public int PersonDataId {get; set;}
public virtual PersonData PersonData {get; set;}
...
}
这不会改变您的三个表:每个表都有一个名为 Id 的主键。员工和客户具有 PersonData 表的外键。不过,如果您已经有一个数据库,您可能需要一些流畅的 API 来匹配列名(不是真正的代码优先吗?)。
回到你的问题
你有一个现有的 Person,由他的 Id 标识,他开始为你工作:你只需添加一个新的 Employee,这个 Person 的外键
var addedEmployee = myDbcontext.Employees.Add(new Employee()
{
PersonId = PersonId,
...
})
如果这个人也有不同的工作,只需添加一个具有相同 PersonId 的新员工。如果他决定退出旧功能:删除旧员工,但保持新员工不变。如果另一个 Person 将执行此 Employee 的功能:只需更改 PersonId。如果员工也成为客户:添加一个 PersonId 等于员工的 PersonId 的新客户。
恕我直言,此解决方案比您尝试保持 Employee / Customer / Person 的主键值相同的解决方案更简单、更自然。如果您仍然想要这个,请阅读Entity Framework Table Per Type (TPT)
推荐阅读
- javascript - 如何在正交坐标系中找到属于同一对角线的点
- sqlite - Cordova:如何同时使用两个 sqlite 插件?
- google-shared-contacts - 2021 年将弃用联系人 API 时如何访问域共享 API?
- sql - 在 BigQuery 中的 json 键组合中计数唯一
- amazon-web-services - 如何从 CloudFormation 中的另一个堆栈导入现有的 S3 存储桶?
- c++ - 在 C++ 中按列对二维数组进行排序
- c++ - Is it legal to return reference to an InputIterator internal state?
- matlab - matlab中数据的衰减率
- excel - 使用两个范围组合两个 SUMIF 语句
- python - Plyer 通知在 android 上不起作用