2012-03-28 9 views
1

中に私はEFとASP.NET MVCを使用していると私は(彼らは/未チェックチェックした内容に基づいて、すなわち)、ユーザの選択に基づいてエンティティを削除しようとしている、このための私のアプローチの確認が必要です。私は「コレクションが変更された。列挙操作が実行されないことがあります。」受信していますforeachの

これを行うには、チェックボックスからフォームから渡されたIDを調べて、データベースにあるものと一致するものを探してから、新しいものを追加してから一致しないものを削除します。続き

は私がもともと持っていたコードです:

 [HttpPost] 
    public ActionResult Edit(int id, FormCollection collection, VMinstanceRole vmodel) 
    { 
     try 
     { 
      var instancerole = db.instanceRoles.Find(id); 

      if (ModelState.IsValid) 
      { 
       UpdateModel<instanceRole>(instancerole, "instanceRole"); 
       var keys = instancerole.rights.Select(c => c.Id); 

       foreach (var pid in vmodel.selectedId.Except(keys)) 
       { 
        var right = new right { Id = pid }; 
        db.rights.Attach(right); 
        instancerole.rights.Add(right); 
       } 

       foreach (var pid in keys.Except(vmodel.selectedId)) 
       { 
        var right = instancerole.rights.Where(c => c.Id == pid).Single(); 
        instancerole.rights.Remove(right); 
       } 


       db.SaveChanges(); 
      } 

      // TODO: Add update logic here 

      return RedirectToAction("Index"); 
     } 
     catch (InvalidCastException e) 
     { 
      return View(); 
     } 
    } 

ただし、次のエラーが「コレクションが変更された。列挙操作が実行されないことがあります。」発表されました

だから、これを試してみて、解決するために、私は別々のリストを保持し、エラーを克服するために、その後tehのリストに基づいて、それを削除することを決めた:

 [HttpPost] 
    public ActionResult Edit(int id, FormCollection collection, VMinstanceRole vmodel) 
    { 
     try 
     { 
      var instancerole = db.instanceRoles.Find(id); 
      List<right> removeList = new List<right>(); 
      if (ModelState.IsValid) 
      { 
       UpdateModel<instanceRole>(instancerole, "instanceRole"); 
       var keys = instancerole.rights.Select(c => c.Id); 

       foreach (var pid in vmodel.selectedId.Except(keys)) 
       { 
        var right = new right { Id = pid }; 
        db.rights.Attach(right); 
        instancerole.rights.Add(right); 
       } 

       foreach (var pid in keys.Except(vmodel.selectedId)) 
       { 
        var right = instancerole.rights.Where(c => c.Id == pid).Single(); 
        removeList.Add(right); 
       } 

       foreach (var right in removeList) 
       { 
        instancerole.rights.Remove(right); 
       } 
       db.SaveChanges(); 
      } 

      // TODO: Add update logic here 

      return RedirectToAction("Index"); 
     } 
     catch (InvalidCastException e) 
     { 
      return View(); 
     } 
    } 

これが動作しているようですが、しかし、私はどうかわからないんだけど私は正しいことをやった。主に私は別のループをしているので。これに接近するより良い方法はありますか、それとも十分ですか?

答えて

0

はこれを試してください:あなたは、foreachループで列挙

foreach (var pid in keys.Except(vmodel.selectedId).ToList()) 
{ 
    var right = instancerole.rights.Where(c => c.Id == pid).Single(); 
    instancerole.rights.Remove(right); 
} 

列挙子は、すでにあなたが最初の項目を削除した瞬間で配置されます。

+0

こんにちはIlya、返信いただきありがとうございます。私はあなたが何を意味するかを見ています。これは私が持っているものよりもずっと良く感じます。ありがとう – user1012500

0

foreachで列挙するときにコレクションを編集できない理由は、ここで単独で文書化されているだけです(脇にある「関連する」リンクをチェックしてください)。シンプルforループやアイテムの除去時にインデックスに改正する - これを使用すると、1つのループを維持することができます。

for (int i = 0; i < max; i++) { 
    //if removing an item 
    //manipulate the index as desired... 
    i--; 
} 
4

標準的なソリューションが1つ見つかりました。あなたの鍵オブジェクトを生成LINQの操作にToListメソッドを呼び出すことであろう作品、他のソリューション:そうでしょう切断元のコレクション上の任意の独立した変更を可能にinstancerolesコレクションからキー。

+0

dasblinkenlightやあ、返信用thaks私は、私は別の変数でToListメソッドを保存すべきか否か少し混乱していたが、私は今それを持っていると思います。私に方向性を教えてくれてありがとう。 – user1012500

関連する問題