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; }
        [...]
    }

このdb関係を更新するには

データベースからのノートの現在の状態を取得する:

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

NoteTagsのリストをクリアし、新しいものを追加してください:

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個のNoteTagsがあります(以前は4個でしたが、5個持っていたので、実際には前回のものと追加したいものの合計です)。しかし、LINQPadに実際にどのように見えるかを見ると、4つの古いNoteTags(変更なし)が表示されます。

私は間違って何をしていますか?

人気のある回答

この拡張機能を使って、選択していないものを削除し、新しく選択したものをリストに追加することができます

    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
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ