2015-11-16 44 views
3

我已經閱讀了許多關於實體框架問題的帖子,其中多了很多,並且它再次讓人頭疼。實體框架中的重複條目在多對多關係中

Colaborador有時間的ICollection的和 時間有Colaborador

的ICollection的

有人說,it's必要附加子實體之前添加上下文(didn't工作對我來說,PK錯誤)。

我使用簡單的注射器,我的上下文是每個請求。

我的關聯表映射這樣的:

  HasMany<Time>(c => c.Times) 
      .WithMany(t => t.Colaboradores) 
      .Map(ct => 
      { 
       ct.MapLeftKey("ColaboradorId"); 
       ct.MapRightKey("TimeId"); 
       ct.ToTable("Receptor"); 
      }); 

它在數據庫中創建的關聯表。 當我嘗試插入Colaborador(實體)時,我在其列表中添加了一些時間(團隊),添加到DbContext,然後SaveChanges()。

當我這樣做時,它會創建一個新的Colaborador,在關聯表(ID)中正確插入,但也會複製時間。

var colaborador = Mapper.Map<ColaboradorViewModel, Colaborador>(colaboradorVm); 
List<TimeViewModel> timesVm = new List<TimeViewModel>(); 
colaboradorVm.TimesSelecionados.ForEach(t => timesVm.Add(_serviceTime.BuscarPorId(t))); 

colaborador.Times = Mapper.Map<ICollection<TimeViewModel>, ICollection<Time>>(timesVm); 

函數BuscarPorId執行Find方法並返回Time。

我已經知道如果我調用Add命令,該實體會將該孩子的狀態標記爲已添加,但是如果我嘗試附加時間或將其狀態更改爲未更改,主鍵錯誤...

foreach (var item in colaborador.Times) 
{     
    lpcContext.Set<Time>().Attach(item); 
    //lpcContext.Entry(item).State = EntityState.Unchanged; 
} 

有什麼辦法告訴實體框架不要插入特定的孩子嗎?那麼只有主表和關聯表被填充?

+0

這是不相關的多對多關係。它總是發生。如果您需要避免添加相關實體,則需要從數據庫中檢索它們(您將用於添加的相同上下文),或者將它們附加到上下文,然後將EntityState設置爲不變 – bubi

+0

@Moho:附加一個實體類型失敗,因爲另一個相同類型的實體已具有相同的主鍵值。 – Maturano

+0

@bubi,我用Find方法檢索時間,然後將它添加到Colaborador的列表中。就在添加的上下文中,我試圖附加(就像上面顯示的一樣),但我得到了Pk錯誤。這不正確嗎? – Maturano

回答

1

Mapper.Map創建未連接到您的上下文新Time對象,所以你必須將它們作爲Unmodified,但它們附着導致由於重複的PK,因爲你的上下文已經跟蹤Time實體的原件另一個錯誤。使用Find方法將檢索這些跟蹤的和本地高速緩存的實體。

找到並使用已連接到您的上下文實體:

相反的:

colaborador.Times = Mapper.Map<ICollection<TimeViewModel>, ICollection<Time>>(timesVm); 

用途:

var times = new List<Time>(); 
var dbSet = lpcContext.Set<Time>(); 

foreach(var t in timesVm) 
{ 
    var time = dbSet.Find(t.Id); 

    if(null == time) 
    { 
     time = Mapper.Map<TimeViewModel, Time>(t); 
    } 

    times.Add(time); 
} 

collaborador.Times = times; 
+0

Moho,timesVm已經擁有我需要的數據,但它在視圖模型中(以前使用_serviceTime.BuscarPorId()...其中BuscarPorId執行Find方法)。 是否真的需要再爲每個id做其他foreach?由於在這一層我沒有訪問的DbSet(我打電話給我這樣做的服務),但我知道他們是相同的上下文(因爲我把它們設置爲每個請求) – Maturano

+1

你已經知道答案因爲你的代碼不起作用; 'Mapper.Map'會創建新的'Time'對象,它們不會附加到您的上下文中,所以您必須將它們附加爲'Unmodified',但附加它們會導致由於重複PK導致的另一個錯誤,因爲您的上下文已經跟蹤'時間'實體。使用Find方法將檢索這些跟蹤的和本地緩存的實體。 – Moho

+0

最後我明白它是如何工作的,我想感謝你@Moho。 – Maturano