Search code examples
c#dynamics-crmdynamics-crm-2013keynotfoundexception

'The given key was not present in the dictionary' - but the key exists


I am currently developing a MS Dynamics CRM 2013 - Plugin. When I try to assign a string-value to a key of a field of an entity it gives me the 'keynotfound'-exception.

This leaves me clueless, because I can verify the key is existing. The key I give is also written correctly, and the data types are compatible, too.

Here's some extra info:

  • I tried resolving the issue with a server reboot. Nothing.
  • Remote Debugging is not an option.
  • I swapped "retrieved.EntityCollection.Entities[i][forField]" with retrieved.EntityCollection.Entities[i]["new_name"] and everything was working fine (kind of pointing out the obvious here, but "new_name" is not the key I try to access).
  • The execution stops @ "if (retrieved.EntityCollection.Entities[i][forField].ToString() != "" && !overwriteExisting)"

Have you got an idea to help me out?

public void GenerateNumberForEntityCollection(string target)
{
    try
    {
        // variables for number generation
        bool overwriteExisting = (bool)preImageEntity["new_overwriteexisting"];
        int suffixstart = (int)preImageEntity["new_suffixstart"];
        string forField= preImageEntity["new_forfield"].ToString();
        string prefix = preImageEntity["new_prefix"].ToString();
        string postfix = preImageEntity["new_postfix"].ToString();
        string separator = preImageEntity["new_separator"].ToString();

        // Build query to get all the entries
        RetrieveMultipleResponse retrieved;
        int PageNumber = 1;
        string PagingCookie = string.Empty;
        int PageSize = 5000;
        string[] Columns = { forField };
        QueryExpression query = new QueryExpression()
        {
            EntityName = target,
            ColumnSet = new ColumnSet(Columns),
            PageInfo = new PagingInfo()
            {
                PageNumber = 1,
                Count = PageSize
            }
        };

        do
        {
            if (PageNumber != 1)
            {
                query.PageInfo.PageNumber = PageNumber;
                query.PageInfo.PagingCookie = PagingCookie;
            }

            RetrieveMultipleRequest retrieve = new RetrieveMultipleRequest();
            retrieve.Query = query;
            retrieved = (RetrieveMultipleResponse)service.Execute(retrieve);

            // Now that all entities are retrieved, iterate through them to gen. the numbers
            int i = 0;
            foreach (Entity entity in retrieved.EntityCollection.Entities)
            {
                if (retrieved.EntityCollection.Entities[i][forField].ToString() != "" && !overwriteExisting)
                {
                    //continue;
                }
                else
                {
                    retrieved.EntityCollection.Entities[i][forField] = prefix + separator + suffixstart.ToString() + separator + postfix;
                }
                suffixstart++;
                service.Update(retrieved.EntityCollection.Entities[i]);
                i++;
            }
            if (retrieved.EntityCollection.MoreRecords)
            {
                PageNumber++;
                PagingCookie = retrieved.EntityCollection.PagingCookie;
            }
        } while (retrieved.EntityCollection.MoreRecords);
    }
    catch (Exception e)
    {
        tracing.Trace("GenerateNumberForEntityCollection: Failed: {0}", e.ToString());
    }
}

Solution

  • When you are querying data in Dynamics CRM it is important to know that record fields having null values in the database are not included in the Attributes collection of the Entity instances being returned.

    Getting a value from an Entity's Attribute with this construct:

    var value = retrieved.EntityCollection.Entities[i][forField].ToString();
    

    succeeds when attribute forField already has a value in the database, but fails when its current value is null.

    Therefore the preferred method to get the attribute values from an entity is GetAttributeValue<T>, like this:

    var value = retrieved.EntityCollection.Entities[i].getAttributeValue<string>(forField);
    

    This method returns the value when the attribute exists in the attribute collection, otherwise it returns null.