2

У меня есть 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

Я сделал ассоциацию в автогенерируемой таблице :

  • CandidateSkills
    • CandidateId SkillId

Теперь я хочу, чтобы обновить навыки candidateId 1 т.е. Тому, кто хочет удалите его SkillId: 2 ie MVC и добавьте новый SkillId: 4 & 5 ie nHibernate & Java соответственно.

Я получаю множество Ids из формы, т.е. 3, 4 5 & & и кандидата Id: 1, С 2 удаляется пользователем.

Мой API, как это:

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

Как обновить кандидатскую запись эффективным способом, делая наименее обращений к базе данных?

ответ

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 в своей модели, чтобы вы могли добавлять/удалять ассоциации без загрузки объектов-кандидатов или навыков.

+0

спасибо @GertArnold –

+0

Или используйте [объекты-заглушки] (http://stackoverflow.com/a/16787524/861716). –

0

Вы можете просто отметить состояние объекта как измененное и сохранить контекст.

public void UpdateCandidate(Candidate candidate) 
{ 
    Context.Entry(candidate).State = EntityState.Modified; 
} 
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; } 


} 

Вам нужно добавить этот класс как DbSet в вашем DbContext классе

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(); 
     } 

} 

контроллер в данном примере у только Пометка кандидатов, чтобы добавить к нашему контекст (в вашей таблице ссылок) и добавление em в db с db.SaveChanges()

Смежные вопросы