有效地更新多对多关系

时间:2013-10-04 14:33:22

标签: asp.net-mvc entity-framework asp.net-mvc-4 entity-framework-5

我有2个模型类。

public class Candidate
{
  public int Id { get; set; }
  public string Name { get; set; }
  public ICollection<Skill> Skills { get; set; }
}

public class Skill
{
  public int Id { get; set; }
  public string Name { get; set; }
  public ICollection<Candidate> Candidates { get; set; }
}

这会创建3个表。

  • 候选人
    • Id名称
    • 1汤姆
    • 2 John

  • 技能
    • Id名称
    • 1 C#
    • 2 MVC
    • 3 SQL
    • 4 nHibernate
    • 5 Java

我在AUTOGENERATED表中建立了关联:

  • CandidateSkills
    • CandidateId SkillId
    • 1 2
    • 1 3

现在我想更新 candidateId 1的技能,即Tom想要删除他的SkillId:2即MVC并添加新的SkillId:4&amp; 5即nHibernate&amp;分别是Java

我从表格中得到 Ids 的集合,即 3,4&amp; 5&amp;候选人Id:1 ,因为2被用户删除。

我的API是这样的:

public Candidate Add(int candidateId, int[] skillIds)
{
    var model = dbContext.candidate.Find(candidateId);
}

如何以有效的方式更新候选记录,进行最少的数据库调用?

3 个答案:

答案 0 :(得分:4)

使用Entity Framework中的多对多关联,您只能使用对象,而不能使用原始Id值。

public void Add(int candidateId, int[] skillIds)
{
    var model = dbContext.candidate.Include(c => c.Skills)
                         .Single(candidateId => c.candidateId == candidateId);

    var skills = dbContext.Skills.Where(s => skillIds.Contains(s.Id)).ToArray();
    foreach (var skill in skills)
    {
        model.Skills.Add(skill);
    }

    dbContext.SaveChanges();
}

您必须在加载技能的情况下获取候选人,因此Include。必须为EF加载技能才能跟踪对集合的更改。

如果优化性能对您来说真的很不错,则必须在模型中创建联结类CandidateSkill类,这样您就可以添加/删除关联而无需加载候选或技能对象。

答案 1 :(得分:2)

public class CandidateToSkill
{
    public Candidate Candidate{ get; set; }
    [Key,Column(Order = 0)]
    public int CandidateID { get; set; }


    [Key,Column(Order = 1)]
    public int SkillID{ get; set; }

    public Skill Skill { get; set; }


} 

您还需要在dbContext类

中将此类添加为DbSet
public class Candidate
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<CandidateToSkill> CandidateSkills{ get; set; }
}

public class Skill
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<CandidateToSkill> SkillCandidates{ get; set; }
}

和控制器代码

public void Add(int candidateId, int[] skillIds)
{
    using (var db = new YourdbContext())
        {
            foreach (int skillID in skillIds )
            {
                 db.CandidateToSkill.Add(new CandidateToSkill(){skillID,candidateId});
            }
            db.SaveChanges();
        }

}

在此示例中,您只标记要添加到我们的上下文中的候选项(在您的链接表中)并使用db.SaveChanges()将em添加到db

答案 2 :(得分:0)

您可以将实体状态标记为已修改并保存上下文。

public void UpdateCandidate(Candidate candidate)
{
   Context.Entry(candidate).State = EntityState.Modified;
}