How do I create relationships in EF Core?

1.7k views Asked by At

I am building a ASP.NET Core 2.0 application with a Web API backend and an Angular 5 front end. For my data access layer I am using Entity Framework Core.

For example, I have two models below that have a relationship.

 public class Project 
{
    [Key]
    public int Id { get; set; }

    public string project_name { get; set; }

    [ForeignKey("Person")]
    public int? pm_person_id { get; set; }

    [ForeignKey("Person")]
    public int? ptl_person_id { get; set; }

    [ForeignKey("pm_person_id")]
    public virtual Person pm_person { get; set; }

    [ForeignKey("ptl_person_id")]
    public virtual Person ptl_person { get; set; }
}



public class Person 
{
    public Person()
    {
        pm_projects = new HashSet<Project>();
        ptl_projects = new HashSet<Project>();
    }

    [Key]
    public int Id { get; set; }

    public string full_name { get; set; }

    [ForeignKey("pm_person_id")]
    public virtual ICollection<Project> pm_projects { get; set; }

    [ForeignKey("ptl_person_id")]
    public virtual ICollection<Project> ptl_projects { get; set; }
}

However when I try and connect to the database and retrieve these to display, EF Core states that it does not understand the relationship between Project.pm_person_id and Person.

I followed the microsoft documentation on EF Core and the ForeignKey attribute is what it recommended, as opposed to defining these in the ModelBuilder. Have I fully established the relationship correctly?

3

There are 3 answers

2
Wiliam Paulino On

in the class Project you must add the using

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

and the class Project should be modeled in this way:

[ForeignKey("pm_person_id")]
public int pm_person_id { get; set; }
public Person Person { get; set; }

and add the icollection in the class Person

public ICollection<Project> Project { get; set; }

try this!

0
Shloime Rosenblum On

For each foreign key put an id property and a property with the datatype of the foreign key class and you don't need any annotations entity framework will understand that it is a foreign key

public class Project 
{
  public int ID { get; set; }

  public string projectName { get; set; }

  public int? pmPersonID { get; set; }
  public Person pmPerson { get; set; }

  public int? ptlPersonID { get; set; }
  public Person ptlPerson { get; set; }
}



public class Person 
{
    public Person()
  {
    pm_projects = new HashSet<Project>();
    ptl_projects = new HashSet<Project>();
  }

  public int ID { get; set; }

  public string fullName { get; set; }

  public int pmPersonId { get; set; }
  public virtual ICollection<Project> pmProjects { get; set; }

  public int ptlProjectsId { get; set; }
  public virtual ICollection<Project> ptlProjects { get; set; }

}

1
AudioBubble On

Not sure exactly what you are looking for here, but is a more in-depth example which may help.

public class Person
{
    public Person()
    {
        PM_Projects = new HashSet<Project>();
        PTL_Projects = new HashSet<Project>();
    }

    [Key]
    [Required]
    public int Id { get; set; }

    public string Full_Name { get; set; }

    public virtual ICollection<Project> PM_Projects { get; set; }

    public virtual ICollection<Project> PTL_Projects { get; set; }
}

public class Project
{
    [Key]
    [Required]
    public int Id { get; set; }

    public string Project_Name { get; set; }

    [ForeignKey("PM_Person")]
    public int PM_Person_Id { get; set; }

    [ForeignKey("PTL_Person")]
    public int PTL_Person_Id { get; set; }

    public virtual Person PM_Person { get; set; }

    public virtual Person PTL_Person { get; set; }
}

The classes for some mapping

public class PersonMap : IEntityTypeConfiguration<Person>
{
    public void Configure(EntityTypeBuilder<Person> builder)
    {

        builder.Property(t => t.Full_Name);

        //table  
        builder.ToTable("People");

        //relationships
        builder.HasMany(s => s.PM_Projects).WithOne(o=>o.PM_Person).OnDelete(DeleteBehavior.Restrict);
        builder.HasMany(s => s.PTL_Projects).WithOne(o => o.PTL_Person).OnDelete(DeleteBehavior.Restrict);
    }
}

public class ProjectMap : IEntityTypeConfiguration<Project>
{
    public void Configure(EntityTypeBuilder<Project> builder)
    {

        builder.Property(t => t.Project_Name);

        //table  
        builder.ToTable("Projects");

        //relationships
        builder.HasOne(s => s.PM_Person).WithMany(d=>d.PM_Projects).OnDelete(DeleteBehavior.Restrict);
        builder.HasOne(s => s.PTL_Person).WithMany(d => d.PTL_Projects).OnDelete(DeleteBehavior.Restrict);

    }
}

On model creating

protected override void OnModelCreating(ModelBuilder builder)
{
        base.OnModelCreating(builder);


        // Customize the ASP.NET Identity model and override the defaults if needed.
        // For example, you can rename the ASP.NET Identity table names and more.
        // Add your customizations after calling base.OnModelCreating(builder);

        //Build identity
        BuildIdentity(builder);

        builder.ApplyConfiguration(new PersonMap());
        builder.ApplyConfiguration(new ProjectMap());
}

Add and run your migrations