混乱局面
我有一种情况,我有两个实体,其中1个从另一个继承,需要映射到两个单独的表,但代码的使用应该围绕这两个实体的基础。
详细信息
public class Team
{
public virtual int Id { get; set; }
public virtual ICollection<Employee> Members { get; set; }
}
public class Employee
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual ICollection<Team> Teams { get; set; }
}
public class EmployeeInfo : Employee
{
public virtual int Id { get; set; }
public virtual decimal Amount { get; set; }
}
我们有一个现有的数据库模式,其中Employee和EmployeeInfo是独立的表,Employe_Info_Id和Employme_Id之间有一个FK。
在我们的系统中,"经理"将使用一组私人信息(比上面列出的更多的属性)(如工资)将员工的添加到系统中,并将他们添加到团队中。系统的其他区域将使用Team或Employee对象进行各种其他操作。如果可以完成映射,我们希望代码非常简单。
当经理创建新员工时,我们希望代码看起来像这样:
public void Foo(string name, decimal pay)
{
// create the employee
var employee = new EmployeeInfo();
employee.Name = name;
employee.Pay = pay;
// add him/her to the team
_team.Employees.Add(employee); // the idea being that consumers of the Team entity would not get the separate employee info properties
// save the context
_context.SaveChanges();
}
最终结果是,EmployeeInfo属性输入EmployeeInfo表,基础Employee数据输入Employme表,并通过关联表TeamEmployees添加到团队。
到目前为止,我正在尝试当前的映射,但在向团队添加员工时,我得到了一个名为"Discriminator"的无效列。
public class TeamConfiguration : EntityTypeConfiguration<Team>
{
public TeamConfiguration()
{
ToTable("Team");
HasKey(t => t.Id);
HasMany(t => t.Members).WithMany(m => m.Teams)
.Map(m =>
{
m.MapLeftKey("Team_Id");
m.MapRightKey("Employee_Id");
m.ToTable("TeamEmployees");
});
}
}
public class EmployeeConfiguration : EntityTypeConfiguration<Employee>
{
public EmployeeConfiguration()
{
ToTable("Employee");
ToTable("EmployeeInfo");
HasKey(t => t.Id);
Property(p => p.Name);
HasMany(m => m.Teams)
.WithMany(t => t.Members)
.Map(m =>
{
m.MapLeftKey("Employee_Id");
m.MapRightKey("Team_Id");
m.ToTable("TeamEmployees");
});
}
}
此外,如果我去掉团队和员工之间的多对多,我会在employee_Id到EmployeeInfo_Id上得到一个FK异常。
谢谢,JR.
Discriminator
是在使用Table Per Hierarchy
方法时添加到表中的列
我想你要找的是"每种类型的表格(TPT)"。按如下方式装饰您的EmployeeInfo
类:
[Table("EmployeeInfo")]
public class EmployeeInfo : Employee
或者在您的OnModelCreating
活动中添加以下内容:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
...
modelBuilder.Entity<EmployeeInfo>().ToTable("EmployeeInfo");
...
}
或者,创建以下类,并像OnModelCreating
方法中的modelBuilder.Configurations.Add(new EmployeeInfoConfiguration());
一样使用它:
public class EmployeeInfoConfiguration : EntityTypeConfiguration<EmployeeInfo>
{
public EmployeeInfoConfiguration()
{
ToTable("EmployeeInfo");
}
}
这将导致EF创建具有必要约束的EmployeeInfo
表。
此外,最好在对象的构造函数中初始化集合,以防止出现null异常。例如在Team
类中:
public Team()
{
this.Employees = new HashSet<Employee>();
}
我准确地复制了你的代码,并更改了以下部分:
public class Team
{
public Team()
{
this.Members = new HashSet<Employee>();
}
public virtual int Id { get; set; }
public virtual ICollection<Employee> Members { get; set; }
}
public class Employee
{
public Employee()
{
this.Teams = new HashSet<Team>();
}
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual ICollection<Team> Teams { get; set; }
}
[Table("EmployeeInfo")]
public class EmployeeInfo : Employee
{
public virtual int Id { get; set; }
public virtual decimal Amount { get; set; }
}
在DbContext中,没有更改:
public partial class TestEntities : DbContext
{
public DbSet<Employee> Employees { get; set; }
public DbSet<EmployeeInfo> Employee_Info { get; set; }
public DbSet<Team> Teams { get; set; }
}
以及您的工作Foo
方法:
public static void Foo(string name, decimal pay)
{
var _team = new Team();
var context = new TestEntities();
context.Teams.Add(_team);
// create the employee
var employee = new EmployeeInfo();
employee.Name = name;
employee.Amount = pay;
context.Employees.Add(employee);
context.SaveChanges();
// add him/her to the team
_team.Members.Add(employee);
// save the context
context.SaveChanges();
}
最后,从EmployeeConfiguration
中删除ToTable("EmployeeInfo");
部分,因为您已经在模式创建事件中正确地提到了这一点。
有关"按类型表"方法的更多信息,请查看这篇很棒的文章。