2014-09-25 48 views
0

我正在研究Code First,EF 6.0並試圖實現Request和Tag表之間的多對多關係。EF代碼中的這種多對多關係有什麼問題 - 首先是

的關係是否正確設置爲:

HasMany(b => b.Tags).WithMany().Map(mc => mc.MapLeftKey("RequestID").MapRightKey("TagID").ToTable("requesttags")); 

一切看起來都沒有問題。但是,在請求插入標籤時,我用三種方法插入:

> if (request.Tags == null) 
>    { 
>     entity.Tags = new List<Tag>(); 
>    } 
>    // 1 way get the tag and then insert. 
>    var tag = _tagService.Get(1); 
       // 2 and 3 way hard code id with the name. 
>    var tags = new List<Tag> {tag, new Tag {Name = ".Net", ID = 2}, new Tag {Name = "C#"}}; 
> 
>    request.Tags.AddRange(tags); 

執行插入操作。但是,當我看到最終結果時:第一個標記已正確引用了參考。但是,對於兩個標籤,即使ID和名稱匹配,仍然會在標籤表中創建新記錄並進行參考。

我的想法是因爲第一個標籤對象是從數據庫中獲取並且被附加。但爲什麼我必須重視?

我該如何解決這個問題?

回答

1

但是爲什麼我必須附上?

因爲它們是斷開的對象並將被視爲新對象。在將tags添加到request.Tags的那一刻,它們都將被標記爲已添加,因爲EF不知道它們都是現有實體。

您可以通過循環Tags來檢查每個標籤的狀態。

request.Tags.AddRange(tags); 
foreach(var tag in tags) 
{ 
    Console.WriteLine(dbContext.Entry(tag).State); 
} 

輸出應該是這樣的:

Unchanged 
Added 
Added 

我該如何解決這個問題?

只是Attach它或將其標記爲Unchanged爲斷開的對象。

dbContext.Entry(tags[1]).State = EntityState.Unchanged; 
// equals to dbContext.Set<Tag>().Attach(tags[1]); 
dbContext.Entry(tags[2]).State = EntityState.Unchanged; 
// equals to dbContext.Set<Tag>().Attach(tags[2]); 

並確保兩個實體真的存在的實體,如果不是DbUpdateException會調用SaveChanges時被拋出。

+0

謝謝你的時間。我明白,我也會遵循。然而,我的印象是,有一些應用程序廣泛的方式來管理它。換句話說,我的所有實體都擁有一個稱爲ID的字段,如果我可以告訴某個EF,那麼這就是您在插入/更新之前通過其檢查和查找的字段。這樣我就不必循環並改變狀態。 – codebased 2014-09-28 01:13:27

+0

@codebased,EF不知道每個斷開連接的對象的狀態,EF將它們視爲新對象,即使該ID不是0或不是Guid Empty,在這種情況下它們仍將被添加。 _Entity Framework負責跟蹤實體在連接到上下文時的狀態,但在斷開連接或N層情況下,您可以讓EF知道您的實體應處於什麼狀態._ - [msdn](http:// msdn .microsoft.com/EN-US /數據/ jj592676.aspx)。如果你正在尋找一個優雅的解決方案,你可以使用[GraphDiff](https://github.com/refactorthis/GraphDiff) – 2014-09-28 07:28:58