状況:私はタグのようなものがあります。ユーザーはいくつかのエンティティのタグのリストを変更できます。エンティティとタグには、多くの関係があります。Entity Frameworkの多対多リレーションを更新する
問題:新しいタグを追加したり、古いタグを削除したり、タグを変更せずに保存したりできます。例えば:前
- :アフター C、B、:タグ
a
が削除されたB、C、D
、タグd
を添加しました。 SQLクエリの数を最小限に抑えてこれを行う最も効率的な方法は何ですか?
考えられる解決策:
私は2つの解決策を見つけましたが、私はすべての古いタグを削除し、比較
// 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は、まずソリューション短所
を照会します。
Include
第二の溶液のプロを使用していないすべてのTags
をすべての関係を削除し、新しいを作成し、関係なく、彼らは
- んが、すべての
第二の溶液の短所を取り除きます:
- すべての新しいタグに
- ロードをロードするためのクエリの多くは、すべての
Tags
この問題に対する最善の解決策は何ですかInclude
を使用していますか?
好奇心の高まりから、 'tagIds'リストだけを持っているとき、これがどのように機能しますか?エンティティに割り当てる*タグの*新しいリストをどのように取得しますか? Idプロパティが割り当てられた新しいタグオブジェクトでリストを作成すると、EFがタグレコードとリンクレコードの両方を挿入しようとしていることがわかります。 –
私はいくつかのテストを行い、これを知っています:1.タグのコレクションを読み込んで新しいコレクションを割り当てます。 2 - 古いコレクションをロードせず、新しいコレクションを割り当てました。結果は両方のコレクションの関連付けになります。 –
@AlexeyMarkov完全性を確認するために、この回答(例:オプション3)に基づいて投稿を更新するか(自己回答を投稿する)、1と2と同じ分析/比較を行うことができますか? –