2016-04-28 40 views
1

下面的方法將一些分離的節點作爲輸入參數。目標是從數據庫加載任何現有的別名,將缺失的節點插入數據庫,並且如果分離的節點的別名實體已經在數據庫中,只需將其設置爲數據庫中的一個。實體框架6 - 分離的實體防止保存重複的導航屬性

但是,在SaveChanges()上,數據庫中已經存在的別名似乎又被插入了。我如何解決這個問題?

internal async Task InsertMissingNodesToDb(INWatchNode[] nodes) 
{ 
    if (nodes.Any(x => x == null)) { 
     Trace.TraceError("Some null element in nodes array in InsertMissingNodesToDb()."); 
     nodes = nodes.Where(x => x != null).ToArray(); 
    } 

    // De-dup nodes based on ID 
    nodes = nodes.GroupBy(x => x.Id).Select(y => y.FirstOrDefault()).ToArray(); 
    List<string> aliasNames = new List<string>(); 

    foreach (var node in nodes) { 
     foreach (var alias in node.Aliases) { 
      if (!aliasNames.Contains(alias)) { 
       aliasNames.Add(alias); 
      } 
     } 
    } 

    using (var dbContext = Application.GetDbContext()) { 
     dbContext.Aliases.Where(x => aliasNames.Contains(x.Alias)).Load(); 

     foreach (var node in nodes) { 
      var entityNode = await dbContext.Nodes.FindAsync(node.Id); 

      if (entityNode == null) { 
       entityNode = node is NWatchNode ? (NWatchNode)node : new NWatchNode(node); 

       for (int i = 0; i < entityNode.AliasEntities.Count; i++) { 
        var currentElement = entityNode.AliasEntities.ElementAt(i); 
        var loadedAlias = dbContext.Aliases.Local. 
         FirstOrDefault(x => x.Alias == currentElement.Alias); 
        if (loadedAlias != null) { 
         currentElement.Id = loadedAlias.Id; 
         currentElement = loadedAlias; 
         dbContext.Entry(loadedAlias).State = EntityState.Unchanged; 
        } 
       } 

       dbContext.Nodes.Add(entityNode); 
      } 
     } 
     await dbContext.SaveChangesAsync(); 
    } 
} 

回答

0

我對這段代碼感到懷疑。

currentElement.Id = loadedAlias.Id; 
currentElement = loadedAlias; // this seems pointless 
dbContext.Entry(loadedAlias).State = EntityState.Unchanged; 

如果你想在這個行做一些事情,我想你需要設置entityNode.AliasEntities.ElementAt(i)loadedAlias - 設置currentElementloadedAlias只是重寫本地實例變量在loadedAlias點,因此看起來毫無意義代碼 - 你沒有通知實體,它的一個有意的孩子應該用這一行指向這個實例。類似以下內容可能會阻止該問題?

for (int i = 0; i < entityNode.AliasEntities.Count; i++) { 
    var currentElement = entityNode.AliasEntities.ElementAt(i); 
    var loadedAlias = dbContext.Aliases.Local. 
     FirstOrDefault(x => x.Alias == currentElement.Alias); 
    if (loadedAlias != null) { 
     currentElement.Id = loadedAlias.Id; 
     entityNode.AliasEntities.ElementAt(i) = loadedAlias; 
     dbContext.Entry(loadedAlias).State = EntityState.Unchanged; 
    } 
} 
+0

'entityNode.AliasEntities.ElementAt(ⅰ)= loadedAlias;'不編譯:( AliasEntites是ICollection的,所以我得到的信息,即左手必須是一個屬性或索引 – blgrnboy

+0

我或許你需要刪除'currentElement',然後添加'loadedAlias'而不是? –

+0

你說得對,我必須做一個'entityNode.AliasEntities.Remove(currentElement);'insetad,然後'entityNode.AliasEntities。添加(loadedAlias);' 偶然的,你知道如果Remove()去掉哈希以找到一個要移除的元素,或者它會使用Id嗎? – blgrnboy