EDF 4.1在多对多关系上映射继承

时间:2011-06-05 22:08:17

标签: entity-framework .net-4.0 mapping entity-framework-4.1

令人困惑的情况 我有一种情况,我有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上找到一个FK例外的EmployeeInfo_Id。

谢谢,JR。

1 个答案:

答案 0 :(得分:3)

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表。

此外,最好在对象的构造函数中初始化集合以防止出现null异常。例如,在Team class:

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部分,因为您已在模式创建活动中正确提及此内容。

有关Table Per Type方法的更多信息,请查看this great article