I want to store multiple values from a dropdown using .NET Core MVC and Entity Framework. I have no idea how to do that. This is my model code.
public class Project
{
[Key]
public int Id { get; set; }
[Required]
public string Title { get; set; }
public string? Description { get; set; }
public List<int> SkillsID { get; set; }
[ValidateNever]
public List<Skill> skills { get; set; }
}
CodePudding user response:
Start here (https://docs.microsoft.com/en-us/ef/core/modeling/relationships?tabs=fluent-api,fluent-api-simple-key,simple-key ) to understand relationships in EF. In your case you will likely want to set up a Many-to-Many relationship between Projects and Skills. This assumes you will have a list of Skills where by each Project associates itself with 0, 1, or many of those skills. In this case you would have classes like:
public class Project
{
// ... project properties.
public virtual ICollection<Skill> Skills { get; protected set; } = new List<Skill>();
}
public class Skill
{
// ... skill properties.
}
When mapped, you tell EF that Project .HasMany(x => x.Skills).WithMany()
as we likely don't need a Projects collection on each individual Skill entity. The last step is telling EF how to associate these two entities. In Many-to-Many relationships this involves a joining table such as a ProjectSkills table:
[tbl:ProjectSkills]
- PK,FK - ProjectId
- PK,FK - SkillId
You don't track lists of FKs in the entity. Think of it from a database perspective. When relating tables together with FKs, you don't have an array or such of FKs within a single row. You use a joining table.
The PK for the table is a composite between the Project ID and Skill ID, where each of those is a FK back to the corresponding table. EF can create this table by convention or you can configure it manually if you want to fine-tune the naming.
If you want to track more detail about the relationship such as tracking a CreatedDate etc. then you will need to map the relationship as an entity which would look like:
public class Project
{
// ... project properties.
public virtual ICollection<ProjectSkill> ProjectSkills { get; protected set; } = new List<ProjectSkill>();
}
public class Skill
{
// ... skill properties.
}
public class ProjectSkill
{
[Key, Column(Order = 0)]
public int ProjectId { get; set; }
[Key, Column(Order = 1)]
public int SkillId { get; set; }
public DateTime CreatedDateTime { get; set; }
// .. Other details about the relationship.
[ForeignKey("ProjectId")]
public virtual Project Project { get; set; }
[ForeignKey("SkillId")]
public virtual Skill Skill { get; set; }
}
You may come across examples for EF core using these joining entities as this was required in earlier versions of EF Core (2, 3.1) for all Many-to-Many relationships.
For a One-to-Many where skills specifically belong to a Project, then a ProjectID would be put into the Skill table. The Project entity would have the same collection of Skills, but the mapping would be a: .HasMany(x => x.Skills).WithOne()
Where the Skill table would contain a ProjectID to associate itself to a given project. EF can represent this relationship as a one-way where Project has the collection and Skill doesn't expose a reference to Project, or bi-directional where you can add a Project reference into Skill. (.HasMany(x => x.Skills).WithOne(x => x.Project)
)