如何在Entity Framework中正确保存多对多关系

时间:2011-06-07 13:11:07

标签: c# entity-framework many-to-many entity-framework-4.1

我目前正在使用以下EF代码第一个模型,该模型在Person和Tag之间存在多对多的关系。

public class person
{
   public Person()
   {
      this.Tags = new List<Tag>();
   }

   public int Id { get; set; }
   public string Name { get; set; }
   public virtual ICollection<Tag> Tags { get; set; }
}

public class Tag
{
   public Tag()
   {
      this.People = new List<Person>();
   }

   public int Id { get; set; }
   public string Name { get; set; }
   public virtual ICollection<Person> People { get; set; }
}

public MyContext : DbContext
{
   public DbSet<Person> People { get; set; }
   public DbSet<Tag> Tags { get; set; }
}

然后我将Json模型传递给包含现有人的MVC控制器,并且正在更新人名,同时在人员标签列表中添加或删除标签。

我遇到了一些问题,正确地将标签与此人相关联。经过大量的试验和错误后,我提出了以下方法。

[HttpPost]
public JsonResult Save(Person person)
{
   //get ids of all tags that are associated with this person.
   var tagIds = new List<int>();
   foreach (var tag in person.Tags)
   {
      tagsIds.Add(tag.Id);
   }

   //clone the person minus the tags
   var personToSave = person;
   personToSave.Tags = new List<Tag>();

   var context = new MyContext();
   var existingTags = (from t in context.Tags
                       where t.People.Count > 0 && t.People.All(p => p.Id == person.Id)
                       select t).ToList();

   //attach the person, so updates to the person object will save.
   context.Entry(personToSave).State = EntityState.Modified;

   if (tagIds.Count > 0)
   {
      //add new tags
      var tags = context.Tags.Where(t => tagIds.Contains(t.Id));
      foreach (var tag in tags)
      {
         //check if tags has no people and not already associated to this person.
         if (tag.People.Count == 0 || tag.People.First(p => p.Id == person.Id) == null)
         {
             personToSave.Tags.Add(tag);
         }
      }

     //remove tags that exist for this person, but were not specified in the list of
     //tags on the person object that was passed into the method.
     foreach(var existingTag in existingTags)
     {
          if (!tagIds.Contains(existingTag.Id)
          {
              context.Tags.Find(existingTag.Id).People.Remove(person);
          }
     }         
   }

   //Finally if no tags were passed in the model and the person has tags, remove them.
   if (tagsIds.Count == 0 && existingTags.Count > 0)
   {
       foreach (var oldTag in existingTags)
       {
           context.Tags.Find(oldTag.Id).People.Remove(person);
       }
   }

   context.SaveChanges();

   var message = string.Format("Saved {0} with {1} tags", person.Name, person.Tags.Count);
   return Json(new {message});

}

所有这些代码似乎都需要添加/删除某个人的标签。我仍然是Entity Framework的新手,所以我觉得我可能错过了一些东西。我想知道我是否有更好的方法来做到这一点。此外,请注意,这是我能够开始工作的第一件事,因此可能会有额外的重构。

0 个答案:

没有答案