Entity Framework 使用非主键列自引用
Entity Framework Self Referencing Using Non-Primary Key Column
我有一名员工 table 可以自行参考以确定组织结构。我在尝试使用 Code-First (POCO) 流畅地进行设置时遇到了一些麻烦。
一条员工记录既有 "Position" 字段,也有 "ReportsTo" 字段,并且没有任何列是主键 (employee.id)。
“ReportsTo”值为“08294”的员工是“员工的直接下属的员工” Position”“08294”的值。
谁能提供一些有关如何首先使用 EF 代码流畅地进行设置的信息...这可能吗?
我尝试了下面的代码,但出现错误:
Employee_Employees_Source_Employee_Employees_Target: : The types of
all properties in the Dependent Role of a referential constraint must
be the same as the corresponding property types in the Principal Role.
The type of property 'ReportsTo' on entity 'Employee' does not match
the type of property 'Id' on entity 'Employee' in the referential
constraint '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 "stuff" 的影响,并且能够执行以下操作:
employee.IsSupervisor(); // based on child employee count.
问题出在关系配置中。如果您想在不使用 FK 的情况下配置一对多关系,您可以这样做:
modelBuilder.Entity<Employee>()
.HasMany(e => e.Employees)
.WithOptional(e => e.Supervisor);
现在,如果您想使用 FK 属性,请将此 属性 添加到您的模型 class:
public class Employee
{
//...
public int SupervisorId { get; set; }
}
并以这种方式映射您的关系:
modelBuilder.Entity<Employee>()
.HasMany(e => e.Employees)
.WithOptional(e => e.Supervisor)
.HasForeignKey(e => e.SupervisorId);
要解决与 ReportTo
和 Position
属性相关的问题,我认为您应该在代码中处理该逻辑。如果你想知道 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' 构造函数中初始化 Employees
。
您得到的错误是因为它试图将 int
类型的 PK 映射到 string
类型的 FK。用户 int
用于所有关键字段。
然后,您需要像这样声明您的 OnModelBuilding:
modelBuilder.Entity<Employee>()
.HasOptional(e => e.Supervisor)
.WithMany()
.HasForeignKey(s => s.ReportsTo);
要获得类似 IsSupervisor()
的内容,您可以利用部分 classes。创建另一个 class 文件,它是一个 public partial class Employee
(并将您原来的文件修改为部分),然后在您的新文件中添加一个 属性 做任何你想做的,并装饰它具有 [NotMapped]
属性。你的可能看起来像 public bool IsSupervisor {get { return (Employees == null) ? false : true; } set {} }
新的部分 class 是你可以在不更改 EF class 的情况下为 POCO 做任何你想做的事情(尽管确保你使用 [NotMapped]
).
我有一名员工 table 可以自行参考以确定组织结构。我在尝试使用 Code-First (POCO) 流畅地进行设置时遇到了一些麻烦。
一条员工记录既有 "Position" 字段,也有 "ReportsTo" 字段,并且没有任何列是主键 (employee.id)。
“ReportsTo”值为“08294”的员工是“员工的直接下属的员工” Position”“08294”的值。
谁能提供一些有关如何首先使用 EF 代码流畅地进行设置的信息...这可能吗?
我尝试了下面的代码,但出现错误:
Employee_Employees_Source_Employee_Employees_Target: : The types of all properties in the Dependent Role of a referential constraint must be the same as the corresponding property types in the Principal Role. The type of property 'ReportsTo' on entity 'Employee' does not match the type of property 'Id' on entity 'Employee' in the referential constraint '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 "stuff" 的影响,并且能够执行以下操作:
employee.IsSupervisor(); // based on child employee count.
问题出在关系配置中。如果您想在不使用 FK 的情况下配置一对多关系,您可以这样做:
modelBuilder.Entity<Employee>()
.HasMany(e => e.Employees)
.WithOptional(e => e.Supervisor);
现在,如果您想使用 FK 属性,请将此 属性 添加到您的模型 class:
public class Employee
{
//...
public int SupervisorId { get; set; }
}
并以这种方式映射您的关系:
modelBuilder.Entity<Employee>()
.HasMany(e => e.Employees)
.WithOptional(e => e.Supervisor)
.HasForeignKey(e => e.SupervisorId);
要解决与 ReportTo
和 Position
属性相关的问题,我认为您应该在代码中处理该逻辑。如果你想知道 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' 构造函数中初始化 Employees
。
您得到的错误是因为它试图将 int
类型的 PK 映射到 string
类型的 FK。用户 int
用于所有关键字段。
然后,您需要像这样声明您的 OnModelBuilding:
modelBuilder.Entity<Employee>()
.HasOptional(e => e.Supervisor)
.WithMany()
.HasForeignKey(s => s.ReportsTo);
要获得类似 IsSupervisor()
的内容,您可以利用部分 classes。创建另一个 class 文件,它是一个 public partial class Employee
(并将您原来的文件修改为部分),然后在您的新文件中添加一个 属性 做任何你想做的,并装饰它具有 [NotMapped]
属性。你的可能看起来像 public bool IsSupervisor {get { return (Employees == null) ? false : true; } set {} }
新的部分 class 是你可以在不更改 EF class 的情况下为 POCO 做任何你想做的事情(尽管确保你使用 [NotMapped]
).