C# 实体框架-多外键问题
我有一个C# 实体框架-多外键问题,c#,entity-framework,ef-code-first,C#,Entity Framework,Ef Code First,我有一个Project模型,它有一个ProjectLead(一个Person外键的实例),这很好用。但是现在我还需要添加一个人员(项目成员)集合,引用相同的人员表,我无法获取实体框架来生成数据库。当我尝试添加Fluent API代码以创建链接表ProjectPerson时,我收到一个错误-“指定的架构无效。错误:由于类型“MyApp.WebApi.Models.Person”不可用,因此未加载关系“MyApp.WebApi.Models.Person”我认为这是因为与ProjectLead已有F
Project
模型,它有一个ProjectLead
(一个Person
外键的实例),这很好用。但是现在我还需要添加一个人员
(项目成员)集合,引用相同的人员
表,我无法获取实体框架来生成数据库。当我尝试添加Fluent API代码以创建链接表ProjectPerson
时,我收到一个错误-“指定的架构无效。错误:由于类型“MyApp.WebApi.Models.Person”不可用,因此未加载关系“MyApp.WebApi.Models.Person”我认为这是因为与ProjectLead
已有FK关系
项目模型:
public class Project
{
[Key]
public int ProjectId { get; set; }
public string Name { get; set; }
// Foreign Key - Project lead (Person)
public int ProjectLeadId { get; set; }
public virtual Person ProjectLead { get; set; }
// Create many to many relationship with People - Team members on this project
public ICollection<Person> People { get; set; }
public Project()
{
People = new HashSet<Person>();
}
}
public class Person
{
[Key]
public int PersonId { get; set; }
public String Firstname { get; set; }
public String Surname { get; set; }
// Create many to many relationship
public ICollection<Project> Projects { get; set; }
public Person()
{
Projects = new HashSet<Project>();
}
}
public class HerculesWebApiContext : DbContext
{
public DbSet<Person> People { get; set; }
public DbSet<Project> Projects { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// This works fine
modelBuilder.Entity<Project>()
.HasRequired(c => c.ProjectLead)
.WithMany(d => d.Projects)
.HasForeignKey(c => c.ProjectLeadId)
.WillCascadeOnDelete(false);
// Adding these lines to create the link table `PersonProjects` causes an error
//modelBuilder.Entity<Person>().HasMany(t => t.Projects).WithMany(t => t.People);
//modelBuilder.Entity<Project>().HasMany(t => t.People).WithMany(t => t.Projects);
}
}
公共类项目
{
[关键]
公共int ProjectId{get;set;}
公共字符串名称{get;set;}
//外键-项目负责人(人)
public int ProjectLeadId{get;set;}
公共虚拟人ProjectLead{get;set;}
//与此项目的人员-团队成员建立多对多关系
公共ICollection人员{get;set;}
公共工程()
{
People=newhashset();
}
}
人物模型:
public class Project
{
[Key]
public int ProjectId { get; set; }
public string Name { get; set; }
// Foreign Key - Project lead (Person)
public int ProjectLeadId { get; set; }
public virtual Person ProjectLead { get; set; }
// Create many to many relationship with People - Team members on this project
public ICollection<Person> People { get; set; }
public Project()
{
People = new HashSet<Person>();
}
}
public class Person
{
[Key]
public int PersonId { get; set; }
public String Firstname { get; set; }
public String Surname { get; set; }
// Create many to many relationship
public ICollection<Project> Projects { get; set; }
public Person()
{
Projects = new HashSet<Project>();
}
}
public class HerculesWebApiContext : DbContext
{
public DbSet<Person> People { get; set; }
public DbSet<Project> Projects { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// This works fine
modelBuilder.Entity<Project>()
.HasRequired(c => c.ProjectLead)
.WithMany(d => d.Projects)
.HasForeignKey(c => c.ProjectLeadId)
.WillCascadeOnDelete(false);
// Adding these lines to create the link table `PersonProjects` causes an error
//modelBuilder.Entity<Person>().HasMany(t => t.Projects).WithMany(t => t.People);
//modelBuilder.Entity<Project>().HasMany(t => t.People).WithMany(t => t.Projects);
}
}
公共类人物
{
[关键]
公共int PersonId{get;set;}
公共字符串名{get;set;}
公共字符串姓氏{get;set;}
//创建多对多关系
公共ICollection项目{get;set;}
公众人士()
{
Projects=newhashset();
}
}
DB上下文:
public class Project
{
[Key]
public int ProjectId { get; set; }
public string Name { get; set; }
// Foreign Key - Project lead (Person)
public int ProjectLeadId { get; set; }
public virtual Person ProjectLead { get; set; }
// Create many to many relationship with People - Team members on this project
public ICollection<Person> People { get; set; }
public Project()
{
People = new HashSet<Person>();
}
}
public class Person
{
[Key]
public int PersonId { get; set; }
public String Firstname { get; set; }
public String Surname { get; set; }
// Create many to many relationship
public ICollection<Project> Projects { get; set; }
public Person()
{
Projects = new HashSet<Project>();
}
}
public class HerculesWebApiContext : DbContext
{
public DbSet<Person> People { get; set; }
public DbSet<Project> Projects { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// This works fine
modelBuilder.Entity<Project>()
.HasRequired(c => c.ProjectLead)
.WithMany(d => d.Projects)
.HasForeignKey(c => c.ProjectLeadId)
.WillCascadeOnDelete(false);
// Adding these lines to create the link table `PersonProjects` causes an error
//modelBuilder.Entity<Person>().HasMany(t => t.Projects).WithMany(t => t.People);
//modelBuilder.Entity<Project>().HasMany(t => t.People).WithMany(t => t.Projects);
}
}
公共类herculesWebAPI上下文:DbContext
{
公共数据库集人物{get;set;}
公共数据库集项目{get;set;}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
//这个很好用
modelBuilder.Entity()
.HasRequired(c=>c.ProjectLead)
.有许多(d=>d.项目)
.HasForeignKey(c=>c.ProjectLeadId)
.WillCascadeOnDelete(假);
//添加这些行以创建链接表“PersonProjects”会导致错误
//modelBuilder.Entity()有许多(t=>t.Projects)。有许多(t=>t.People);
//modelBuilder.Entity()有许多(t=>t.People)。有许多(t=>t.Projects);
}
}
我想我可能需要使用
InverseProperty
属性,但我不确定在这种情况下应该使用哪个属性?您能明确定义联接表吗?所以,定义一个ProjectPeople关系,并使代码如下所示
public class ProjectPerson{
[Key]
public int ProjectPersonId { get; set; }
[ForeignKey("Project")]
public int? ProjectId {get;set;}
public virtual Project {get;set;}
[ForeignKey("Person")]
public int? PersonId {get;set;}
public virtual Person {get;set;}
public string RelationshipType {get;set;}
}
public class Project
{
[Key]
public int ProjectId { get; set; }
public string Name { get; set; }
// Foreign Key - Project lead (Person)
public int ProjectLeadId { get; set; }
public virtual Person ProjectLead { get; set; }
// Create many to many relationship with People - Team members on this project
public virtual ICollection<ProjectPerson> ProjectPeople { get; set; }
public Project()
{
ProjectPerson = new HashSet<ProjectPerson>();
}
然后你的另外两个班会像这样
public class ProjectPerson{
[Key]
public int ProjectPersonId { get; set; }
[ForeignKey("Project")]
public int? ProjectId {get;set;}
public virtual Project {get;set;}
[ForeignKey("Person")]
public int? PersonId {get;set;}
public virtual Person {get;set;}
public string RelationshipType {get;set;}
}
public class Project
{
[Key]
public int ProjectId { get; set; }
public string Name { get; set; }
// Foreign Key - Project lead (Person)
public int ProjectLeadId { get; set; }
public virtual Person ProjectLead { get; set; }
// Create many to many relationship with People - Team members on this project
public virtual ICollection<ProjectPerson> ProjectPeople { get; set; }
public Project()
{
ProjectPerson = new HashSet<ProjectPerson>();
}
公共类项目
{
[关键]
公共int ProjectId{get;set;}
公共字符串名称{get;set;}
//外键-项目负责人(人)
public int ProjectLeadId{get;set;}
公共虚拟人ProjectLead{get;set;}
//与此项目的人员-团队成员建立多对多关系
公共虚拟ICollection项目人员{get;set;}
公共工程()
{
ProjectPerson=newhashset();
}
}
还有这个
Public class Person
{
[Key]
public int PersonId { get; set; }
public String Firstname { get; set; }
public String Surname { get; set; }
// Create many to many relationship
public virtual ICollection<ProjectPerson> ProjectPeople { get; set; }
public Person()
{
ProjectPerson = new HashSet<ProjectPerson>();
}
}
公共类人物
{
[关键]
公共int PersonId{get;set;}
公共字符串名{get;set;}
公共字符串姓氏{get;set;}
//创建多对多关系
公共虚拟ICollection项目人员{get;set;}
公众人士()
{
ProjectPerson=newhashset();
}
}
如果您能准确地说出您遇到的错误,可能会有所帮助。“导致错误”毫无意义。谢谢,在帖子中添加了错误消息。为什么还要添加流畅的配置?您的配置所做的与正常约定所做的相同。其次,您可能希望使您的收藏成为虚拟的,因为您可能不希望每次查询项目时都包括所有相关人员。@ErikFunkenbusch-谢谢,是的,我将使收藏成为虚拟的。我使用fluent API是因为我有一个非标准外键IDProjectLeadId
。谢谢,这是个好主意。那么,每次我用人员获取项目时,我如何避免收回整个ProjectPeople
表?我会在我的控制器中这样做吗,比如返回db.Projects.Include(“ProjectPeople”).Where(e=>e.projectd==id).AsEnumerable()代码>可以,但在这种情况下,可以使用延迟加载,避免抢占关系并删除“Include”。然后,当你想查询你的加入关系时,你可以做大量的操作来过滤你的结果。(另外,作为提示,我将在视图模型中放置类似的内容,以防止控制器显式定义查询。)