2013-07-31 64 views
0

我有一個System.InvalidOperationException:集合被修改錯誤,您可以看到控制檯here的輸出。System.InvalidOperationException:集合被修改錯誤

這是我的代碼,我刪除了很多行,這樣結構會更容易閱讀。

static public void searchCode2(Dictionary<string, string> MList) 
    { 

     using (SqlConnection connection3 = new SqlConnection(ConfigurationManager.ConnectionStrings["DB"].ConnectionString)) 
     { 


      connection3.Open(); 
      SqlCommand command2 = new SqlCommand(null, connection3); 

      var keysWithMatchingValues = MList.Where(p => Equals(p.Value, "0")).Select(p => p.Key); 

      // ce for devrait macher, meme s'il y plusieurs requetes 
      // Tthe fallowing line is where the error point out. 
      foreach (var key in keysWithMatchingValues) 
      { 

       Console.WriteLine(" missing list"); 
       string[] motToCut = key.ToString().Split(' '); 
       Dictionary<string, int> MoviesListMissing = new Dictionary<string, int>(); 
       Dictionary<string, string> MoviesListMissingCode = new Dictionary<string, string>(); 
       Dictionary<string, DateTime> MoviesListMissingDate = new Dictionary<string, DateTime>(); 


       //// on va chercher si un des elements du dico n'a pas été récupéré. 
       command2.CommandText = ""; 
       int counter = 0; 

       foreach (string word_cutted in motToCut) 
       { 
        // on considere que les mots qui ont plus d'une lettre 
        if (word_cutted.Length > 1) 
        { 

         command2.CommandText += "select Code, Titre, Date from Data where Titre LIKE '%" + word_cutted + "%';"; 
         counter++; 
         Console.WriteLine("word_cutted : {0} ", word_cutted); 
        } 
       } 

       command2.Prepare(); // Calling Prepare after having set the Commandtext and parameters. 

       SqlDataReader reader2 = command2.ExecuteReader(); 


       try 
       { 



        for (int i = 0; i < counter; i++) 
        { 
         //CODES 
        } 
        bool MoviesListMissingisEmpty = (MoviesListMissing.Count == 0); 
        if (!MoviesListMissingisEmpty) 
        { 


         //CODES 
        } 

        // liste le dictionnaire 
        foreach (string key2 in MList.Keys) 
        { 
         Console.WriteLine("Last version : {0}, {1} ", key2, MList[key2]); 
        } 


       } 
       catch (Exception e) 
       { 
        //Console.WriteLine("{0} Exception caught.", e); 
        Console.WriteLine("Last version : {0}", e); 
       } 
       finally 
       { 
        // Always call Close when done reading. 
        reader2.Close(); 

       } 

      } 

      connection3.Close(); 
      // THIS WON'T PRINT 
      Console.WriteLine(" Avant var key in keysWithMatchingValues "); 



     } 


    } 

出於某種原因,什麼後

connection3.Close(); 

將無法​​正常工作,而且我想不通的原因,我把。在一些類似的話題中,據說使用鎖定功能,但我不在哪裏。 (我嘗試了一些地方,但它沒有工作)。

下面是完整的代碼,如果它可以幫助:

static public void searchCode2(Dictionary<string, string> MList) 
    { 

     using (SqlConnection connection3 = new SqlConnection(ConfigurationManager.ConnectionStrings["DistriDBEntities2"].ConnectionString)) 
     { 


      connection3.Open(); 
      SqlCommand command2 = new SqlCommand(null, connection3); 

      DateTime today = DateTime.Now; 
      bool pbBool = false; 
      string motFinal = ""; 
      var keysWithMatchingValues = MList.Where(p => Equals(p.Value, "0")).Select(p => p.Key); 
      //Where(p => p.Value == "a").Select(p => p.Key); 

      // ce for devrait macher, meme s'il y plusieurs requetes 

      foreach (var key in keysWithMatchingValues) 
      { 

       pbBool = true; 
       Console.WriteLine(" missing list"); 
       //literaltest.Text += "<br/>" + motFinal + ", original: " + key + "<br/>"; 
       string[] motToCut = key.ToString().Split(' '); 
       Dictionary<string, int> MoviesListMissing = new Dictionary<string, int>(); 
       Dictionary<string, string> MoviesListMissingCode = new Dictionary<string, string>(); 
       Dictionary<string, DateTime> MoviesListMissingDate = new Dictionary<string, DateTime>(); 


       //// on va chercher si un des elements du dico n'a pas été récupéré. 
       command2.CommandText = ""; 
       int counter = 0; 

       foreach (string word_cutted in motToCut) 
       { 
        // on considere que les mots qui ont plus d'une lettre 
        if (word_cutted.Length > 1) 
        { 

         command2.CommandText += "select Code, Titre, Date from Data where Titre LIKE '%" + word_cutted + "%';"; 
         counter++; 
         Console.WriteLine("word_cutted : {0} ", word_cutted); 
        } 
       } 

       command2.Prepare(); // Calling Prepare after having set the Commandtext and parameters. 

       //literaltest.Text += "<br/> on rentre dans le try apres word_cutted : "; 

       SqlDataReader reader2 = command2.ExecuteReader(); 


       try 
       { 


        int resultCounter = 1; 
        bool resultUnique = false; 
        string bontitre = ""; 
        for (int i = 0; i < counter; i++) 
        { 
         if (i == 0) 
         { 
          while (reader2.Read()) 
          { 
           //literaltest.Text += "<br/> si i = 0 "; 
           if (reader2[1].ToString().Length > 0) 
           { 
            if (!MoviesListMissing.ContainsKey(reader2[1].ToString())) 
            { 
             //literaltest.Text += "<br/> i = 0 mot : " + reader2[0].ToString() + "," + reader2[1].ToString(); 
             MoviesListMissing.Add(reader2[1].ToString(), 0); 
             MoviesListMissingCode.Add(reader2[1].ToString(), reader2[0].ToString()); 
             bontitre = reader2[1].ToString(); 
             resultCounter++; 
             if (reader2[2].ToString().Length > 0) 
             { 
              DateTime dt = Convert.ToDateTime(reader2[2].ToString()); 
              //literaltest.Text += "<br/> date Conversion orginal:" + reader2[2].ToString() + " new : " + dt.ToString("dd/MM/yyyy"); 
              MoviesListMissingDate.Add(reader2[1].ToString(), dt); 
             } 
            } 
           } 
          } 
         } 

         else if (!resultUnique) 
         { 
          // on réinitialise le compteur 
          resultCounter = 1; 
          reader2.NextResult(); 
          while (reader2.Read()) 
          { 
           if (reader2[1].ToString().Length > 0) 
           { 
            //literaltest.Text += "<br/> i : " + i + " mot : " + reader2[0].ToString() + "," + reader2[1].ToString(); 
            if (!MoviesListMissing.ContainsKey(reader2[1].ToString())) 
            { 
             MoviesListMissing.Add(reader2[1].ToString(), 0); 
             MoviesListMissingCode.Add(reader2[1].ToString(), reader2[0].ToString()); 
             MoviesListMissingDate.Add(reader2[1].ToString(), Convert.ToDateTime(reader2[2].ToString())); 
             bontitre = reader2[1].ToString(); 
            } 
            else 
            { 
             //on incremente le nombre de point. 
             MoviesListMissing[reader2[1].ToString()] += 1; 
             bontitre = reader2[1].ToString(); 
            } 
            resultCounter++; 
           } 
          } 
         } 
         if (resultCounter == 2) 
         { 
          // si on a eu qu'un retour lors d'une requete pour un mot alors c'est la bonne 
          resultUnique = true; 
          Console.WriteLine("ResultUnique true"); 
          //break; 
         } 
        } 
        bool MoviesListMissingisEmpty = (MoviesListMissing.Count == 0); 
        if (!MoviesListMissingisEmpty) 
        { 
         if (resultUnique == false) 
         { 
          // liste le dictionnaire 
          int keyMax = 0; 
          string trueKey = MoviesListMissing.Keys.First(); 
          string falseKey = ""; 
          bool unique = true; 
          // on regarde quel titre a le plus de point. 
          foreach (string cle in MoviesListMissing.Keys) 
          { 
           if (MoviesListMissing[cle] > keyMax) 
           { 
            keyMax = MoviesListMissing[cle]; 
            trueKey = cle; 
            unique = true; 
            falseKey = ""; 
           } 
           else if (MoviesListMissing[cle] == keyMax) 
           { 
            unique = false; 
            falseKey += cle + ", "; 
           } 
          } 
          Console.WriteLine("Le bon titre est : {0} ", trueKey); 
          Console.WriteLine("Le bon titre est unique ? : {0} falsekey: {1}", unique.ToString(), falseKey); 
          // si le nombre max est détenue par un seul titre 
          if (unique) 
          { 
           bontitre = trueKey; 
           // on rajoute le code 
           MList[key.ToString()] = MoviesListMissingCode[trueKey]; 
          } 
          else 
          // on regarde la date 
          { 

           string[] CuttedByDate = falseKey.ToString().Split(' '); 
           DateTime bestDate = MoviesListMissingDate[CuttedByDate[0]]; 
           bontitre = CuttedByDate[0]; 
           foreach (string wordDate in CuttedByDate) 
           { 
            if ((Math.Abs(today.Subtract(MoviesListMissingDate[CuttedByDate[0]]).Days)) < Math.Abs(today.Subtract(bestDate).Days)) 
            { 
             bontitre = wordDate; 
            } 
           } 
          } 
         } 
         else 
         { 
          Console.WriteLine("Le bon titre trouvé de maniere unique : {0} ", bontitre); 
          MList[key.ToString()] = MoviesListMissingCode[bontitre]; 
         } 
        } 

        // liste le dictionnaire 
        foreach (string key2 in MList.Keys) 
        { 
         Console.WriteLine("Last version : {0}, {1} ", key2, MList[key2]); 
        } 



       } 
       catch (Exception e) 
       { 
        //Console.WriteLine("{0} Exception caught.", e); 
        Console.WriteLine("Last version : {0}", e); 
       } 
       finally 
       { 
        // Always call Close when done reading. 
        reader2.Close(); 

       } 

      } 

      connection3.Close(); 
      Console.WriteLine(" Avant var key in keysWithMatchingValues ");    

     } 


    } 
+0

請顯示你所得到的堆棧跟蹤。我覺得很難相信它是拋出異常的「Close」。我懷疑這個問題實際上是在你剪掉的一些代碼中。如果你能製作一個簡短但完整的程序來證明問題,那將是最好的。 –

+0

對不起,我不確定什麼是堆棧跟蹤,也許你是指我在開始的圖像? – Exia0890

+1

您可能已經省略了導致此異常的實際行。造成這種情況的唯一原因是,如果您要在foreach循環中向keysWithMatchingValues集合添加/刪除某些內容。 –

回答

2

好吧,這就是問題所在 - 你修改MList,而你通過基於它懶洋洋地評估查詢迭代:

MList[key.ToString()] = MoviesListMissingCode[bontitre]; 

MList[key.ToString()] = MoviesListMissingCode[trueKey]; 

你不允許這樣做。

解決這個問題最簡單的方法就是將拷貝的鍵/值對作爲查詢的一部分。所以這個:

var keysWithMatchingValues = MList.Where(p => Equals(p.Value, "0")).Select(p => p.Key); 

可以成爲:

var keysWithMatchingValues = MList.ToList() 
            .Where(p => Equals(p.Value, "0")) 
            .Select(p => p.Key); 

雖然作爲個人我把它改寫:

var keysWithMatchingValues = MList.ToList() 
            .Where(p => p.Value == "0") 
            .Select(p => p.Key); 

在這一點上,你沒事修改MList爲你迭代超過keysWithMatchingValues,因爲它們是分開的。

(我也打算把這個龐大的方法分解成更小的方法。)

+0

感謝它的工作,雖然我承認我不確定問題是什麼,爲什麼你解決了它。該守則確實相當大,有很多案件要處理,這並不容易。 – Exia0890

+0

@ Exia0890:基本上,當你迭代它時,你正在改變你正在迭代的集合。這在幾乎所有.NET集合中都是禁止的。 –

+0

我明白了,我認爲keysWithMatchingValues是一個完全與MList分離的對象,但似乎並非如此。不管怎樣,謝謝。 – Exia0890

相關問題