令人困惑的情况
我遇到的情况是,我有2个实体,其中1个继承自另一个实体,需要映射到2个单独的表,但是代码使用应围绕2个实体的基础。
细节
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是单独的表,并且在EmployeeInfo_Id和Employee_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数据输入到Employee表中,并通过关联表TeamEmployees添加到Team中。
到目前为止,我正在尝试当前的映射,但是得到了一个名为“ 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");
...
}
或者,创建以下类,并在
modelBuilder.Configurations.Add(new EmployeeInfoConfiguration());
方法中像OnModelCreating
一样使用它:public class EmployeeInfoConfiguration : EntityTypeConfiguration<EmployeeInfo>
{
public EmployeeInfoConfiguration()
{
ToTable("EmployeeInfo");
}
}
这将导致EF创建具有必要约束的
EmployeeInfo
表。同样,最好在对象的构造函数中初始化集合,以防止出现空异常。例如在
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();
}
最后,由于已在模式创建事件中正确提到了
ToTable("EmployeeInfo");
部分,因此从EmployeeConfiguration
中删除了部分。有关按表类型方法的更多信息,请查看this great article。
关于entity-framework - EF 4.1多对多关系上的映射继承,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6246212/