System.InvalidOperationException:集合被修改错误 [英] System.InvalidOperationException: Collection was modified error

查看:55
本文介绍了System.InvalidOperationException:集合被修改错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 System.InvalidOperationException: Collection was modified 错误,你可以看到控制台的输出这里 .

I have a System.InvalidOperationException: Collection was modified error, you can see the output of the console here .

这是我的代码,我删除了很多行,以便结构更易于阅读.

Here is my code, I removed many lines, so that the structure would be easier to read.

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 ");



        }


    }

出于某种原因,我在后面放了什么

For some reason what I put after

 connection3.Close();

不起作用,我想不出原因.在一些类似的主题中,据说使用了锁定功能,但我不知道在哪里.(我尝试了一些地方,但没有奏效).

won't work, and I can't figure out the reason. In some similar topics, it is said to use the lock function, but i don't where. ( I tried some places but it did not work).

如果有帮助,这里是完整的代码:

Here is the complete code if it may help:

   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 ");             

        }


    }

推荐答案

好吧,这就是问题所在 - 您正在修改 MList 而您正在迭代懒惰评估 基于它的查询:

Okay, this is the problem - you're modifying MList while you're iterating through a lazily evaluated query based on it:

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

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

你不能这样做.

解决此问题的最简单方法是将键/值对的副本作为查询的一部分.所以这个:

The simplest way to fix this is simply to take a copy of the key/value pairs as part of the query. So this:

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);

尽管我个人会将其重写为:

Although personally I'd rewrite it as:

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

此时,您可以在迭代 keysWithMatchingValues 时修改 MList,因为它们是分开的.

At this point, you're fine to modify MList as you iterate over keysWithMatchingValues, because they're separated.

(我也会把这个庞大的方法分解成更小的方法.)

(I'd also break up this mammoth method into smaller ones.)

这篇关于System.InvalidOperationException:集合被修改错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆