如何更新Entity Framework 7中的多對多關係?

asp.net entity-framework entity-framework-core

tl; dr:我有一些具有多對多關係的數據庫。當我編輯它的數據並調用SaveChanges()時,數據庫中沒有任何更改。

完整問題:

我遇到了很奇怪的問題。我想更新多對多關係,但它不想改變。我的模型看起來像這樣(我只發布了這個在這個問題中很重要的部分):

public class Note
    {
        public Note()
        {
            NoteTags = new HashSet<NoteTag>()
        }

        public int NoteId { get; set; }
        public virtual ICollection<NoteTag> NoteTags { get; set; }
        [...]
    }

public class NoteTag
    {
        public int NoteId { get; set; }
        public Note Note { get; set; }

        public int TagId { get; set; }
        public Tag Tag { get; set; }
    }

public class Tag
    {
        public Tag()
        {
            NoteTags = new HashSet<NoteTag>();
        }

        public int TagId { get; set; }
        public string Name { get; set; }
        public virtual ICollection<NoteTag> NoteTags { get; set; }
        [...]
    }

我該怎麼做來更新這個數據庫關係:

從數據庫獲取當前的Note狀態:

Note noteInDb = db.Notes.Include(x => x.NoteTags).ThenInclude(x => x.Tag).AsNoTracking().FirstOrDefault(x => x.NoteId == note.NoteId);

清除NoteTag列表並添加新的:

noteInDb.NoteTags = new List<NoteTag>();
noteInDb = TagsToAddToTags(note);

TagsToAddToTags做了什麼:它在數據庫中找到適當的標籤,並將它們添加到List <>,如下所示:

note.NoteTags.Add(new NoteTag { Tag = tagInDb });

然後我對數據庫說我修改了一些數據並保存:

db.Entry(noteInDb).State = EntityState.Modified;
db.SaveChanges();

noteInDb變量看起來正是我想要它保存到數據庫時的樣子。 遺憾的是,當我查看數據庫時,它看起來仍然像以前一樣。

奇怪的是,當我在SaveChanges()之後寫這行時:

Note noteInDb2 = db.Notes.Include(x=>x.NoteTags).ThenInclude(x=>x.Tag).FirstOrDefault(x => x.NoteId == note.NoteId);

我可以看到noteInDb2有9個NoteTag(之前它有4個,我希望它有5個,所以這實際上是以前和我想要添加的內容的總和)。但是當我去LINQPad看它的樣子時,它會顯示我4個舊的NoteTag(沒有變化)。

我究竟做錯了什麼?

熱門答案

您可以使用此擴展程序刪除未選中的內容並將新選擇的內容添加到列表中

    public static void TryUpdateManyToMany<T, TKey>(this DbContext db, IEnumerable<T> currentItems, IEnumerable<T> newItems, Func<T, TKey> getKey) where T : class
    {
        db.Set<T>().RemoveRange(currentItems.Except(newItems, getKey));
        db.Set<T>().AddRange(newItems.Except(currentItems, getKey));
    }

    public static IEnumerable<T> Except<T, TKey>(this IEnumerable<T> items, IEnumerable<T> other, Func<T, TKey> getKeyFunc)
    {
        return items
            .GroupJoin(other, getKeyFunc, getKeyFunc, (item, tempItems) => new { item, tempItems })
            .SelectMany(t => t.tempItems.DefaultIfEmpty(), (t, temp) => new { t, temp })
            .Where(t => ReferenceEquals(null, t.temp) || t.temp.Equals(default(T)))
            .Select(t => t.t.item);
    }

使用它看起來像這樣

 var model = db.Notes
             .Include(x => x.NoteTags )
             .FirstOrDefault(x => x.NoteId == note.NoteId );

 db.TryUpdateManyToMany(model.NoteTags, listOfNewTagIds
 .Select(x => new NoteTag
 {
     TagId = x,
     NoteId = note.NoteId
 }), x => x.TagId);


Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow