首先在 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
并保留 Person
和 Customer
,ID 为 10。
虽然这可行,但需要您自己进行 ID 编号。数据库很难检查你是否做了非法的事情,比如杀了一个 Person
但它仍然是你的 Employees
.
不要用一个 ID 来标识您的 Employee
、您的 Person
和您的 Customer
,而是给他们自己的主键。给 Employee
和 Customer
一个指向它们 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)
我正在使用 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
并保留 Person
和 Customer
,ID 为 10。
虽然这可行,但需要您自己进行 ID 编号。数据库很难检查你是否做了非法的事情,比如杀了一个 Person
但它仍然是你的 Employees
.
不要用一个 ID 来标识您的 Employee
、您的 Person
和您的 Customer
,而是给他们自己的主键。给 Employee
和 Customer
一个指向它们 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)