令人困惑的情况
我遇到的情况是,我有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/

10-15 12:56