2

I'm trying to loop through items in a ASP c# Listbox, During the loop I intend to get the current value from the listbox and use it to fetch another value from the DB, then using the DB retrieved value to trigger another action (insert to dynamics CRM Database). I'm getting the error:

Collection was modified; enumeration operation may not execute.

Below is my code, any ideas what I am doing wrong?

foreach (object item in SelectedHobbies.Items)
{
    string hobby = SelectedHobbies.Items.ToString();
    string sql = "select cba_hobbyid from cba_hobby where cba_hobby = '" + hobby + "'";
    string hobbyId = Global_Class.GetSqlValue2(sql, "cba_hobbyid");

    try
    {
        using (OrganizationServiceProxy organizationServiceProxy = new OrganizationServiceProxy(this.OrganizationUri_prod, this.HomeRealmUri, this.Credentials, null))
        {
            IOrganizationService organizationService = organizationServiceProxy;
            // Entity contact = new Entity("contact");
            EntityReferenceCollection relatedEntities = new EntityReferenceCollection();
            relatedEntities.Add(new EntityReference("contact", new Guid(hobbyId)));
            Relationship relationship = new Relationship("vrp_cba_hobby_contact");
            organizationService.Associate("contact", new Guid(contactId), relationship, relatedEntities);
            }

    }
    catch (Exception exception1)
    {
        Exception exception = exception1;
    }
}
haldo
  • 14,512
  • 5
  • 46
  • 52
Nelson Kibet
  • 41
  • 1
  • 1
  • 6
  • Hello!Welcome to SO. Does this answer your question?https://stackoverflow.com/questions/1538817/looping-through-all-items-in-listbox –  Dec 04 '19 at 10:20
  • Apart from the original question there are couple of more issues that I detect and would like to address but, is this code ALL the code in the `foreach` block or you have omited sum. because I can't see where the error could arise – Emad Dec 04 '19 at 10:22
  • Is this 'string hobby = SelectedHobbies.Items.ToString();' correct or should it be 'string hobby = item.ToString();'? I'm not sure if it is related to the error that's why I'm asking. – verbedr Dec 04 '19 at 10:27
  • actually this error would arise if you modify `SelectedHobbies.Items`, but in your posted code I don't see any clear indication of it. Another possibility is that you change the underlying data bound data collection. Could you please post the code where you fill the listbox with items? – Mong Zhu Dec 04 '19 at 10:56
  • what does the method: `Associate` do? – Mong Zhu Dec 04 '19 at 11:42
  • @MongZhu IOrganizationService.Associate is a Ms dynamic CRM method that Creates a link between records. – Nelson Kibet Dec 04 '19 at 12:12
  • @Emad i haven't omitted any code, I have another button that picks items from a dropdown to the Listbox, triggered on demand here: protected void btnaddtolist_Click1(object sender, EventArgs e) { SelectedHobbies.Items.Add(drpHobbies.SelectedItem.Text); } – Nelson Kibet Dec 04 '19 at 12:14
  • @verbedr both works,but still the same error Line 1319: string hobbyId = Global_Class.GetSqlValue2(sql, "cba_hobbyid"); Line 1320: Line 1321: Line 1322: Line 1323: try Source File: C:\Users\nelson.langat\Documents\Visual Studio 2015\Projects\CSSP LIVE\CBA Customer Portal V2.1 - LIVE\CBA Customer Portal V2\MyProfile.aspx.cs Line: 1321 Stack Trace: [InvalidOperationException: Collection was modified; enumeration operation may not execute.] System.Collections.ArrayListEnumeratorSimple.MoveNext() +12957656 – Nelson Kibet Dec 04 '19 at 12:30
  • please show us the implementation of the `GetSqlValue2` method – Mong Zhu Dec 04 '19 at 13:13
  • @NelsonKibet the full error message added more information to the question. The problem is not in this part of the code but inside the function Global_Class.GetSqlValue2. Can you add that part of the code? – verbedr Dec 04 '19 at 13:15
  • Below is the code for the method GetSQLValue2 // public static string GetSqlValue2(string _sql, string column) { string slqval = "";try { SqlConnection con = new SqlConnection(CBACRM_MSCRM); con.Open(); SqlCommand cmd2 = new SqlCommand(_sql, con); using (SqlDataReader reader = cmd2.ExecuteReader()){ if (reader.Read()) {slqval = reader[column].ToString();} }con.Close(); }catch () { } return slqval; – Nelson Kibet Dec 05 '19 at 08:04
  • @NelsonKibet your exception and source code are not in sync. The error happens on an empty line. – verbedr Dec 05 '19 at 20:57

2 Answers2

1

This exception is typical when an enumeration is ongoing and you touch the backing collection again.

So where and how does this happen:

// at this line you start enumerating the your collection
foreach (object item in SelectedHobbies.Items)
{
    // **** and here probably you are restarting the enumeration?
    // as pointed out the above statement is incorrect there is not enough
    // information point to the step that is changing the collection
    // backing the enumeration in the original post
    string hobby = SelectedHobbies.Items.ToString();
...

Possible solution is to make a new backing collection

foreach (object item in SelectedHobbies.Items.Cast<ListItem>().ToList()) // create a new list which has its own array backing the collecton
{
    string hobby = SelectedHobbies.Items.ToString();
...
verbedr
  • 1,784
  • 1
  • 15
  • 18
  • 1
    "// and here probably you are restarting the enumeration?" this sounds like you are guessing.... why would a `ToString()` call restart the enumeration? can you back up your thesis? Actually this would only print the class name, something like "System.Windows.Forms.ListBox+ObjectCollection" (taken from a Winforms example) – Mong Zhu Dec 04 '19 at 11:00
  • 1
    @MongZhu sorry you are right checked the code and listitemcollection does not reimplement ToString(). Will update the answer. But it does puzzels me what is causing the exception. – verbedr Dec 04 '19 at 11:54
  • @verbedr, thank you for your response, I have tried this suggestion with no success. SelectHobbies is a Listbox (Asp.net control) apparently does support ToList, see below error: *'ListItemCollection' does not contain a definition for 'ToList' and no extension method 'ToList' accepting a first argument of type 'ListItemCollection' could be found (are you missing a using directive or an assembly reference?)* – Nelson Kibet Dec 04 '19 at 12:07
  • @NelsonKibet I made the mistake to just assume things and should have checked it before typing my answer. As the ListItemCollection is a non generic collection, the ToList does not work you first need to cast (will update the answer). But having read your other comment I do not think this will solve your problem – verbedr Dec 04 '19 at 13:12
0

Looks like a duplicate of this question: Collection was modified; enumeration operation may not execute

Your code is different but the root cause of the error is the same. The error message is trying to tell you that the collection is being changed while you are looping through it.

Imagine cycling through a deck of cards but someone is slipping in or taking new cards while you are halfway through.

Calling "ToList()" will create a List from an IEnumerable, as mentioned in the Microsoft documentation: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.tolist?view=netframework-4.8

What I think you're trying to do is this:

foreach (object item in SelectedHobbies.Items.ToList())
{
    string hobby = item.Value.ToString();
    string sql = "select cba_hobbyid from cba_hobby where cba_hobby = '" + hobby + "'";
333Mhz
  • 899
  • 3
  • 10
  • 21