首先在 entity framework 代码中转换为派生类型

Casting to a derived type in entity framework code first

我正在使用 EntityFramework 6,代码优先,使用 MVC C#。 我有几个看起来像这样的简单实体:

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 framework 也会创建一个新的 Person 记录.有谁知道实现这一目标的简单方法?我认为设计是正确的,因为 Employee 是一个 Person,因此对于这种情况,继承优于组合无疑是正确的选择。

我可以自己写一些 SQL 来将我需要的记录插入到 Employee table 中,或者我可以删除旧记录并用新记录替换它(它会附带一个一大堆外键问题),但如果我这样做,我就接受了 Entity Framework 本质上让我失败了一个非常简单和常见的要求。有没有办法解决这个问题?

提前感谢您的回答。

你的问题的原因是 tables 和它们的列对你来说不是很清楚。

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

一个人可能会改变他的地址,他甚至可能会改变他的名字、性别或生日,因为数据库仍然是同一个人。只有换了他的Id,才真正变了一个Person。

显然您有 Persons 个还不是 Employee。如果 Person 开始为你工作,是否意味着他变成了另一个 Person?他的 ID 应该改变吗?

您可以决定,如果 ID 为 10 的 Person 变为 Employee,您将创建一个 ID 为 10 的 Employee 对象,如果此 Person 也成为一个 Customer 你创建一个 ID 为 10 的 Customer 对象。如果 Employee 停止为你工作,你删除 ID 为 10 的 Employee 并保留 PersonCustomer,ID 为 10。

虽然这可行,但需要您自己进行 ID 编号。数据库很难检查你是否做了非法的事情,比如杀了一个 Person 但它仍然是你的 Employees.

不要用一个 ID 来标识您的 Employee、您的 Person 和您的 Customer,而是给他们自己的主键。给 EmployeeCustomer 一个指向它们 Person 的外键。事实上,Person 更像是 PersonData。 Employee IS not a Person, Employee HAS Person 数据

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

这不会改变您的三个 table:每个 table 都有一个名为 Id 的主键。 Employees 和 Customers 有一个指向 PersonData table 的外键。如果您已经有一个数据库(不是真正的代码优先,是吗?),您可能需要一些流畅的 API 来匹配列名。

回到你的问题

你有一个现有的 Person,由他的 Id 标识,他开始为你工作:你只需添加一个新的 Employee,这个 Person 使用外键

var addedEmployee = myDbcontext.Employees.Add(new Employee()
{
     PersonId = PersonId,
     ...
})

如果这个人也有不同的工作,只需添加一个具有相同 PersonId 的新员工。如果他决定退出旧职能:解雇旧员工,但保留新员工。如果不同的 Person 将执行此 Employee 的功能:只需更改 PersonId。如果 Employee 也变成了 Customer:添加一个 PersonId 等于 Employee 的 PersonId 的新 Customer。

恕我直言,这个解决方案比您尝试让员工/客户/人员的主键值相同的解决方案更简单、更自然。如果您仍然想要这个,请阅读 Entity Framework Table Per Type (TPT)