locked
Handle key not found exception RRS feed

  • Question

  • I'm writing a wpf application and I'm trying to get details out from a selected order.

    My current problem is handling a field where no data has been entered. For example the field billtp_line1 isn't compulsory.

    I've tried using an if function testing for a null value but this doesn't work. I've put the relevant code below.

    The exact error I'm getting is 'KeyNotFoundException was unhandled' with the message 'The given key was not present in the dictionary.'

    Cheers,

    Chris

     Guid locationID = (Guid)listBox1.SelectedValue;
    
                QueryExpression orderQuery = new QueryExpression("salesorder");
                string[] orders = { "name", "salesorderid"};
    
                orderQuery.ColumnSet = new ColumnSet(orders);
                orderQuery.AddOrder("name", OrderType.Descending);
    
                RetrieveRequest req = new RetrieveRequest();
                req.Target = new EntityReference("salesorder", locationID);
                req.ColumnSet = new ColumnSet(true);
    
    var resp = OrgService.Execute(req) as RetrieveResponse;
    
     if (resp.Entity["billto_line1"] == null)
                {
                    label4.Content = "No address line 1";
                }
                else
                {
                    label4.Content = resp.Entity["billto_line1"].ToString();
                }


    • Edited by Chris0123456 Friday, March 9, 2012 2:24 PM error correction
    Friday, March 9, 2012 2:21 PM

Answers

  • Retrieve request only returns an entity with the requested columns. In the above code in the orders array you have only requested for name and salesorderid that is the reason the code returns a key not found error. Change the code to include names of all columns that you need in the orders array or you coukd use AllColumns to read data of all fields in the entity.

    In addition make sure to use if contains to check if key exists before trying to read from it.

    HTH

    Sam 


    Dynamics CRM MVP | Inogic | http://inogic.blogspot.com| news at inogic dot com

    If this post answers your question, please click "Mark As Answer" on the post and "Mark as Helpful"

    • Proposed as answer by Sam - Inogic Saturday, March 10, 2012 1:03 AM
    • Marked as answer by Chris0123456 Monday, March 12, 2012 9:18 AM
    Saturday, March 10, 2012 1:02 AM

All replies

  • Hi Chris:

    You'll want to use one of the built in entity functions as a test.  Entity.GetAttributeValue(<key>) will usually return a null if there is no value in the key field.  Or you can use Entity.Attributes.ContainsKey(<key>) to determine if it exists.

    Friday, March 9, 2012 2:28 PM
  • As JBaeske said you need to check whether the attribute exists and use a default if necessary. I wrote some extension methods which help with this.

    I have 2 versions of an extension method called GetTypedValue, one returns the default for the type if the attribute doesn't exist and with the other you can supply a default. Be warned that default(string) is null so you would need to use the one with a supplied default.

    Using GetTypedValue in your code would look something like this:

                    label4.Content = resp.Entity.GetTypedValue("billto_line1", String.Empty); // returns string.empty if billto_line1 not found

    If you are using the version with the default value the compiler can infer the type, if not you have to supply it:

                    label4.Content = resp.Entity.GetTypedValue<string>("billto_line1"); // returns null if billto_line1 not found

    The methods also handle AliasedValues automatically (these occur when you used LinkedEntity in your query to do joins).

    Here's the code:

        public static class EntityExtensions
        {
    
            /// <summary>
            /// Returns the Id from an entity reference or default(Guid)
            /// </summary>
            /// <param name="entity">Entity</param>
            /// <param name="attributeName">Attribute Name</param>
            /// <returns>Guid, either reference Id or default(Guid)</returns>
            public static Guid GetEntityReferenceId(this Entity entity, string attributeName)
            {
                if (entity.Attributes.ContainsKey(attributeName))
                {
                    return GetTypedValue<EntityReference>(entity, attributeName).Id;
                }
    
                return default(Guid);
            }
    
    
            /// <summary>
            /// Returns the integer from an optionset value or zero if it doesn't exist
            /// </summary>
            /// <param name="entity">Entity</param>
            /// <param name="attributeName">Attribute Name</param>
            /// <returns>Integer value</returns>
            public static int GetOptionSetValue(this Entity entity, string attributeName)
            {
                return GetOptionSetValue(entity, attributeName, 0);
            }
    
    
            /// <summary>
            /// Returns the integer from an optionset value or the dafaultValue if not found
            /// </summary>
            /// <param name="entity">Entity</param>
            /// <param name="attributeName">Attribute Name</param>
            /// <param name="defaultValue">Default optionset value</param>
            /// <returns>Integer value</returns>
            public static int GetOptionSetValue(this Entity entity, string attributeName, int defaultValue)
            {
                if (entity.Attributes.ContainsKey(attributeName))
                {
                    return GetTypedValue<OptionSetValue>(entity, attributeName).Value;
                }
    
                return defaultValue;
            }
    
    
            /// <summary>
            /// Gets a typed value from an entity. If not found the type default is returned
            /// </summary>
            /// <typeparam name="T">Expected Type</typeparam>
            /// <param name="entity">Entity</param>
            /// <param name="attributeName">Attribute name</param>
            /// <returns>Value or default(T) if not found</returns>
            public static T GetTypedValue<T>(this Entity entity, string attributeName)
            {
                return GetTypedValue(entity, attributeName, default(T));
            }
    
            /// <summary>
            /// Gets a typed value from an entity
            /// </summary>
            /// <typeparam name="T">Expected Type</typeparam>
            /// <param name="entity">Entity</param>
            /// <param name="attributeName">Attribute name</param>
            /// <param name="defaultValue">Default value if not found</param>
            /// <returns>Value or default if not found</returns>
            public static T GetTypedValue<T>(this Entity entity, string attributeName, T defaultValue)
            {
    
                if (entity.Attributes.ContainsKey(attributeName))
                {
                    return ReturnAttributeValue<T>(entity[attributeName]);
                }
    
                return defaultValue;
            }
    
            private static T ReturnAttributeValue<T>(object attributeValue)
            {
                AliasedValue aliasedValue = attributeValue as AliasedValue;
                if (aliasedValue != null)
                {
                    return (T)(aliasedValue).Value;
                }
    
                return (T) attributeValue;
    
            }
    
        }





    Friday, March 9, 2012 5:37 PM
  • Retrieve request only returns an entity with the requested columns. In the above code in the orders array you have only requested for name and salesorderid that is the reason the code returns a key not found error. Change the code to include names of all columns that you need in the orders array or you coukd use AllColumns to read data of all fields in the entity.

    In addition make sure to use if contains to check if key exists before trying to read from it.

    HTH

    Sam 


    Dynamics CRM MVP | Inogic | http://inogic.blogspot.com| news at inogic dot com

    If this post answers your question, please click "Mark As Answer" on the post and "Mark as Helpful"

    • Proposed as answer by Sam - Inogic Saturday, March 10, 2012 1:03 AM
    • Marked as answer by Chris0123456 Monday, March 12, 2012 9:18 AM
    Saturday, March 10, 2012 1:02 AM
  • Retrieve request only returns an entity with the requested columns. In the above code in the orders array you have only requested for name and salesorderid that is the reason the code returns a key not found error. Change the code to include names of all columns that you need in the orders array or you coukd use AllColumns to read data of all fields in the entity.

    In addition make sure to use if contains to check if key exists before trying to read from it.

    HTH

    Sam 


    Dynamics CRM MVP | Inogic| http://inogic.blogspot.com| news at inogic dot com

    If this post answers your question, please click "Mark As Answer" on the post and "Mark as Helpful"

    Many thanks for this, it works now (until the next issue!)

    Many thanks,

    Chris

    Monday, March 12, 2012 9:21 AM