2016-04-28 5 views
1

以下のメソッドは、いくつかの独立したノードを入力パラメータとして受け取ります。目的は、データベースから既存のエイリアスをロードし、欠落したノードをデータベースに挿入し、デタッチされたノードのエイリアスエンティティがすでにデータベースに存在する場合は、データベースのエイリアスエンティティに設定するだけです。Entity Framework 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; 

あなたが何かをする問題の行をしたい場合、私はあなたがloadedAliasentityNode.AliasEntities.ElementAt(i)を設定する必要があると思う - loadedAliasからcurrentElementを設定するだけでloadedAliasを指すようにローカルインスタンス変数をオーバーライドし、そのように無意味のように思えるされますコード - エンティティに、その意図された子の1人がその行でこのインスタンスを指すように通知していません。次のような問題が発生しないようにしますか?

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(I)= loadedAlias;'コンパイルされない:( AliasEntitesこといるICollectionであるので、私は左手がプロパティまたはインデクサーでなければならないというメッセージを取得 – blgrnboy

+0

Iでした'currentElement'を削除してから' loadedAlias'を追加する必要がありますか? –

+0

あなたは正しく、entityNode.AliasEntities.Remove(currentElement); 'insetad'、' entityNode.AliasEntities'を実行しなければなりませんでした。追加(loadedAlias); ' Remove()が削除する要素を見つけるためにハッシュを解除するか、それともIdを使用するのかを知っていますか? – blgrnboy

関連する問題