Alexey Markov
Alexey Markov

Reputation: 1566

Update many-to-many relations in Entity Framework

Situation: I have something like a tags: user can change list of tags for some entity. Entity and tag has-many-to many relation.

Problem: user can add some new tags, remove some old tags and keep some tags without changing. For example:

Tag a was deleted, tag d was added. What is most efficient way to do this with minimizing number of SQL queries?

Possible solutions:

I found two solutions, but I don't think they are good

  1. Delete all old tags and add new

    // entityId - editing entity's id
    // tagIds   - new tags ids
    
    var entity _entityRepository.GetAll()
         .Include(x => x.Tags)
         .FirstOrDefault(x => x.Id == entityId);
    entity.Tags.RemoveAll();
    
    // Add new tags
    entity.Tags = _tagsRepository.GetAll()
         .Where(x => tagIds.Contains(x.Id)); //Yes, this .Contains works
    
    _entityRepository.Update(entity);
    
  2. Compare old list of tags with new list of tags and add or remove to make them equivalent.

    // entityId - editing entity's id
    // tagIds   - new tags ids
    
    var entity _entityRepository.GetAll()
         .Include(x => x.Tags)
         .FirstOrDefault(x => x.Id == entityId);
    
     // Add tags which not exists in entity.Tag
     foreach (var tagId in tagIds)
     {
         if (!entity.Tags.Any(x => x.Id == tagId))
         {
             //A lot of queiries!
             var newTag = _tagsRepository.GetAll()
                     .FirstOrDefault(x => x.Id == tagId);
             entity.Tags.Add(newTag);
         }
     }
    
     // Remove tags whic not exists in tagIds
     // Assuming Tags is IList<T> and we can use []
     int i = 0;
    
     while (i < entity.Tags.Count)
     {
         if (!tagIds.Contains(entity.Tags[i].Id))
             entity.Tags.RemoveAt(i);
         else
             i++;
     }
    
     _entityRepository.Update(entity);
    

Solutions pros and cons

First solution pros:

First solution cons:

Second solution pros:

Second solution cons:

What is the best solution for this problem?

Upvotes: 1

Views: 78

Answers (1)

hyankov
hyankov

Reputation: 4130

Don't compare anything, don't implement 'logic' which checks which flags were removed and which added.

Instead, just assign a new list of tags to your entity and tell Entity Framework to save the object. It will figure out on its own which ones have to be removed and which ones to be added.

Upvotes: 2

Related Questions