2017-01-19 168 views
1

情況:我有類似標籤的東西:用戶可以更改某個實體的標籤列表。實體和標籤具有多對多的關係。更新實體框架中的多對多關係

問題:用戶可以添加一些新的標籤,刪除一些舊的標籤,並保持一些標籤不變。例如:

  • 前: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); 
    

解決方案的利弊

第一解決方案的優點:

  • 一些SQL查詢

第一解決方案缺點:

  • 刪除所有關係,並建立新的,不管根本
  • 加載所有Tags使用Include

第二類解決方案的優點,他們改變:

  • 否刪除所有

第二類解決方案利弊:

  • 用於裝載每一個新的標籤
  • 加載大量的查詢所有Tags使用Include

,這是什麼問題的最佳解決方案?

回答

2

不要比較任何東西,不要執行'邏輯'來檢查哪些標誌被刪除,哪些被添加。

相反,只需向實體分配一個新的標籤列表,然後告訴實體框架保存該對象。它將自己弄清楚哪些必須被刪除,哪些被添加。

+0

出於好奇,當你只有'tagIds'列表時,這是如何工作的?你如何獲得你分配給你的實體的新的標籤清單?如果您使用僅分配了Id屬性的新標記對象創建列表,我的測試顯示EF嘗試插入標記記錄和鏈接記錄。 –

+0

我做了一些測試,並知道這一點:1.你加載你的標籤集合並分配新的集合 - 它的工作原理。 2 - 您沒有加載舊收藏並分配新的 - 結果將是兩個收藏的關聯。 –

+0

@AlexeyMarkov爲了保持完整性,您可以根據此答案(例如選項3)更新您的文章(或發佈自我答案)並與工作實施一致(例如選項3),並與1和2進行相同的分析/比較。 –