1
情況:我有類似標籤的東西:用戶可以更改某個實體的標籤列表。實體和標籤具有多對多的關係。更新實體框架中的多對多關係
問題:用戶可以添加一些新的標籤,刪除一些舊的標籤,並保持一些標籤不變。例如:
- 前:A,B,C
- 後:B,C,d
標籤a
被刪除,標籤d
加入。什麼是最有效的方法來最小化SQL查詢的數量?
可能的解決方案:
我發現了兩個解決方案,但我不認爲他們是很好的
刪除所有舊標籤,並添加新的
// 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);
比較帶有新標籤列表的舊標籤列表,並添加或刪除它們以使它們等同。
// 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
,這是什麼問題的最佳解決方案?
出於好奇,當你只有'tagIds'列表時,這是如何工作的?你如何獲得你分配給你的實體的新的標籤清單?如果您使用僅分配了Id屬性的新標記對象創建列表,我的測試顯示EF嘗試插入標記記錄和鏈接記錄。 –
我做了一些測試,並知道這一點:1.你加載你的標籤集合並分配新的集合 - 它的工作原理。 2 - 您沒有加載舊收藏並分配新的 - 結果將是兩個收藏的關聯。 –
@AlexeyMarkov爲了保持完整性,您可以根據此答案(例如選項3)更新您的文章(或發佈自我答案)並與工作實施一致(例如選項3),並與1和2進行相同的分析/比較。 –