2016-02-13 155 views
3

tl; dr:我有一些有多對多關係的數據庫。當我編輯它的數據並調用SaveChanges()時,數據庫中沒有任何變化。如何更新實體框架7中的多對多關係?

全問題:

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

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 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作用:它找到合適的數據庫標籤,並將它們添加到列表<>這樣的:

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箇舊的NoteTag(沒有改變)。

我在做什麼錯?

回答

0

我認爲你需要移動你的代碼。由於您使用AsNoTracking檢索數據,因此只有在將實體的狀態設置爲修改後,纔會跟蹤更改。所以在你調用TagsToAddToTags之前,調用db.Entry(noteInDb).State = EntityState.Modified;

+0

以及使用這個擴展我做了,除去未選中並添加新的選擇列表

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); } 

,它仍然無法正常工作。當我調用SaveChanges時,我可以以某種方式檢查實體框架將更改哪些數據? EF是否保留正在對數據庫進行查詢的地方?這會有很大幫助,因爲我不知道當我調用SaveChanges()時EF正在做什麼。() – Piotrek

+0

您可以通過添加跟蹤提供程序來跟蹤查詢,但是您可以在SQL Server分析器中輕鬆跟蹤它們。添加它們後,您可以檢查實體的狀態,這可能是最好的起點。 db.Entry(newNoteTag).State就在你開始保存更改之前。 –

2

您可以使用它看起來像這樣

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);