使用非主键列的实体框架自引用

时间:2015-02-09 16:44:40

标签: c# entity-framework

我有一个自我引用的员工表来确定组织结构。我在尝试使用Code-First(POCO)流畅地设置它时遇到了一些麻烦。

员工记录包含"职位" 字段和" ReportsTo" 字段,且两个列都不是主键(employee.id)。

拥有" ReportsTo "价值" 08294 " ,是员工直接报告的员工,其职位为职位"价值" 08294 "。

任何人都可以提供一些关于如何首先使用EF代码进行设置的信息,流利地说......有可能吗?

我尝试了下面的代码并收到错误:

  

Employee_Employees_Source_Employee_Employees_Target ::所有类型   参照约束的从属角色中的所有属性都必须   与主体角色中的相应属性类型相同。   财产的类型' ReportsTo'实体'员工'不匹配   财产的类型' Id'实体'员工'在参考   约束' Employee_Employees'。

Employee.cs

public class Employee
{
     public int Id  { get; set; } //pk 
     public string Position { get; set; } // i.e. 06895
     public string ReportsTo{ get; set; } // i.e. 08294         

     public virtual Employee Supervisor { get; set; }
     public virtual ICollection<Employee> Employees { get; set; }
}

DbContext

modelBuilder.Entity<Employee>()
                .HasMany(e => e.Employees)
                .WithOptional(e => e.Supervisor)
                .HasForeignKey(e => e.ReportsTo);

我认为最重要的是,我想让POCO免于EF&#34;东西&#34;并能够做类似的事情:

employee.IsSupervisor(); // based on child employee count. 

2 个答案:

答案 0 :(得分:2)

问题出在关系配置中。如果要在不使用FK的情况下配置一对多关系,可以执行以下操作:

modelBuilder.Entity<Employee>()
            .HasMany(e => e.Employees)
            .WithOptional(e => e.Supervisor);

现在,如果要使用FK属性,请将此属性添加到模型类中:

public class Employee
{
  //...
  public int SupervisorId  { get; set; }
}

以这种方式映射你的关系:

modelBuilder.Entity<Employee>()
            .HasMany(e => e.Employees)
            .WithOptional(e => e.Supervisor)
            .HasForeignKey(e => e.SupervisorId);

要解决与ReportToPosition属性相关的问题,我认为您应该在代码中处理该逻辑。如果您想知道Employee是否是基于Employees属性计数的主管,您可以使用NotMapped属性:

 public class Employee
{
  [NotMapped]
  public bool IsSupervisor
  {
     get
     {
         return Employess.Count>0
     }
  }
}

您可以使用Fluent Api执行相同的操作:

modelBuilder.Entity<Employee>().Ignore(e => e.IsSupervisor);

PS:请记住在您的class'constructor中初始化Employees

答案 1 :(得分:-1)

您得到的错误是因为它试图将int类型的PK映射到string类型的FK。用户int用于所有关键字段。

然后,你需要像这样声明你的OnModelBuilding:

modelBuilder.Entity<Employee>()
.HasOptional(e => e.Supervisor)
.WithMany()
.HasForeignKey(s => s.ReportsTo);

要获得类似IsSupervisor()的内容,您可以利用部分类。创建另一个类文件public partial class Employee(并将原始文件修改为部分文件),然后在新文件中添加一个可以执行任何操作的属性,并使用[NotMapped]属性进行修饰。您可能看起来像public bool IsSupervisor {get { return (Employees == null) ? false : true; } set {} }新的分部类是您可以在不更改EF类的情况下为POCO执行任何操作的地方(尽管请确保使用[NotMapped])。