Inheritance 首先在实体框架代码中强制转换为派生类型

Inheritance 首先在实体框架代码中强制转换为派生类型,inheritance,orm,casting,entity-framework-6,ef-code-first,Inheritance,Orm,Casting,Entity Framework 6,Ef Code First,我使用的是EntityFramework6,代码优先,MVC#。 我有两个简单的实体,如下所示: 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

我使用的是EntityFramework6,代码优先,MVC#。 我有两个简单的实体,如下所示:

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; }
}
但是C#不允许将基类型强制转换为子类型,所以我不能这样做,如果我创建一个新的员工记录,那么实体框架也将创建一个新的人员记录。有人知道一个简单的方法来实现这一点吗?我认为这个设计是正确的,因为员工是一个人,所以继承而不是组成肯定是这个案例的正确选择

我可以自己编写一些SQL来将所需的记录插入Employee表,或者删除旧记录并用新记录替换它(这会带来大量外键问题),但如果这样做,我接受Entity Framework在一个非常简单和常见的需求方面根本没有满足我的要求。这是没有办法的吗


提前感谢您的回答。

问题的原因是表及其列对您来说不是很清楚

数据库中的每个对象都有一个主键,用于标识对象的属性。对象的属性可能会改变,对象表示的对象将是同一个对象

一个人可能会改变他的地址,他甚至可能会改变他的名字、性别或生日,因为数据库中的人仍然是同一个人。只有当你改变他的身份,他才真正变成另一个人

显然,您有
人员
,他们还不是
员工
。如果
开始为你工作,这是否意味着他变成了另一个
?他的身份证应该换吗

您可以决定,如果Id为10的
人员
成为
员工
,则创建Id为10的
员工
对象,如果该
人员
也成为
客户
则创建Id为10的
客户
对象。如果
员工
停止为您工作,您将删除Id为10的
员工
,并保留Id为10的
人员
客户

虽然这可以工作,但它需要您自己进行Id编号。数据库很难检查你是否做了非法的事情,比如杀死一个仍然是你的
员工之一的

不要用一个Id来识别您的
员工
、您的
人员
和您的
客户
,而是给他们自己的主键。给
员工
客户
一个外键给他们所在的
人员
。事实上,这个人更像是
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来匹配列名(不是真正的先编码吗?)

回到你的问题

您有一个现有的人员,由其Id标识,他开始为您工作:您只需添加一个新员工,并将外键添加到此人

var addedEmployee = myDbcontext.Employees.Add(new Employee()
{
     PersonId = PersonId,
     ...
})
如果此人也有不同的工作,只需添加具有相同PersonId的新员工即可。如果他决定退出旧功能:删除旧员工,但保留新员工不变。如果另一个人将执行此员工的职能:仅更改PersonId。如果该员工也成为客户:添加一个PersonId等于该员工PersonId的新客户


IMHO此解决方案比您试图让员工/客户/个人的主键值相同的解决方案更简单、更自然。如果您仍然需要此功能,请阅读

为什么不能简单地创建新员工()
,然后从
person
复制所有相应的属性?如果存在已附加到同一上下文的
人员
,并且您为
员工
设置了适当的
Id
字段,EF可能不会创建新的
人员
var addedEmployee = myDbcontext.Employees.Add(new Employee()
{
     PersonId = PersonId,
     ...
})