更新实体框架中的多对多关系

时间:2017-01-19 10:26:44

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

情况:我有类似标签的东西:用户可以更改某个实体的标签列表。实体和标签有很多关系。

问题:用户可以添加一些新标记,删除一些旧标记并保留一些标记而不进行更改。例如:

  • 之前:a,b,c
  • 之后:b,c, d

标记a已删除,标记d已添加。使用最少的SQL查询数量,最有效的方法是什么?

可能的解决方案

我找到了两个解决方案,但我认为它们不是很好

  1. 删除所有旧标记并添加新标记

    // 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. 将旧的标签列表与新的标签列表进行比较,然后添加或删除以使它们等效。

    // 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);
    
  3. 解决方案的利弊

    第一个解决方案专业人士:

    • 很少有SQL查询

    第一个解决方案:

    • 删除所有关系并创建新关系,无论他们是否更改
    • 使用Tags
    • 加载所有Include

    第二个解决方案专业人士:

    • 不删除全部

    第二个解决方案:

    • 加载每个新标记的很多查询
    • 使用Tags
    • 加载所有Include

    这个问题的最佳解决方案是什么?

1 个答案:

答案 0 :(得分:2)

不要比较任何事情,不要实施逻辑&#39;它检查删除了哪些标志以及添加了哪些标志。

相反,只需为您的实体分配一个新的标签列表,并告诉Entity Framework保存该对象。它将自己弄清楚哪些必须被删除以及哪些要添加。