【问题标题】:'The given key was not present in the dictionary' - but the key exists'给定的键不在字典中' - 但键存在
【发布时间】:2016-08-14 19:12:35
【问题描述】:

我目前正在开发一个 MS Dynamics CRM 2013 - 插件。 当我尝试将字符串值分配给实体字段的键时,它给了我“keynotfound”异常。

这让我一无所知,因为我可以验证密钥是否存在。我给的key也写对了,数据类型也兼容。

这里有一些额外的信息:

  • 我尝试通过重新启动服务器来解决问题。什么都没有。
  • 远程调试不是一个选项。
  • 我将“retrieved.EntityCollection.Entities[i][forField]”替换为 retrieved.EntityCollection.Entities[i]["new_name"] 并且一切正常(在这里指出了明显的问题,但“new_name”不是我尝试访问的密钥)。
  • 执行停止 @ "if (retrieved.EntityCollection.Entities[i][forField].ToString() != "" && !overwriteExisting)"

你有什么想法可以帮助我吗?

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

【问题讨论】:

    标签: c# dynamics-crm dynamics-crm-2013 keynotfoundexception


    【解决方案1】:

    当您在 Dynamics CRM 中查询数据时,重要的是要知道数据库中具有 null 值的记录字段不包含在返回的 Entity 实例的 Attributes 集合中。

    使用此构造从EntityAttribute 获取值:

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

    当属性forField在数据库中已有值时成功,但当其当前值为null失败

    因此,从实体中获取属性值的首选方法是GetAttributeValue<T>,如下所示:

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

    当属性集合中存在该属性时,该方法返回值,否则返回null

    【讨论】:

      【解决方案2】:

      您如何验证密钥是否存在?

      如果字段中的数据为空,则实体实例将不包含该键,即使您在查询的 ColumnSet 中指定它也是如此。

      这将返回一个布尔值,指示该键是否存在于实体中。您可以在尝试读取属性之前执行此控制。

      var attributeExists = retrieved.EntityCollection.Entities[i].Contains(forField) 
      

      如果该字段为空,您所做的下面的控件将导致您收到异常。只需确保该属性之前存在即可。

      retrieved.EntityCollection.Entities[i][forField].ToString() != ""
      

      此外,如果查询未返回任何记录,您将获得空引用异常。让您对retrieve.EntityCollection.Entities 进行空检查。

      【讨论】:

      • 我不建议检查属性集合是否实际包含特定成员。首选方法是使用GetAttribute&lt;T&gt; 方法。此外,IOrganizationService.RetrieveMultiple 返回的DataCollection&lt;Entity&gt;(如在retrieved.EntyCollection.Entities 中)始终存在,因此也不需要null 检查。
      【解决方案3】:

      如果其中的任何字段 (new_forfield,new_prefix,new_postfix,new_separator) 具有空值, 该列不存在于检索到的对象中,您正在尝试获取空列 preImageEntity["new_forfield"] 的值,这将引发 keynotfound'-exception
      所以改代码

      string forField= preImageEntity["new_forfield"].ToString();
      string prefix = preImageEntity["new_prefix"].ToString();
      string postfix = preImageEntity["new_postfix"].ToString();
      string separator = preImageEntity["new_separator"].ToString();
      

      string forField = preImageEntity.Attributes.Contains("new_forfield")? preImageEntity["new_forfield"].ToString():"";
      string prefix = preImageEntity.Attributes.Contains("new_forfield") ? preImageEntity["new_prefix"].ToString() : "";
      string postfix = preImageEntity.Attributes.Contains("new_forfield") ? preImageEntity["new_postfix"].ToString() : "";
      string separator = preImageEntity.Attributes.Contains("new_forfield") ? preImageEntity["new_separator"].ToString() : "";  
      

      这将检查字段,如果它存在,则将值解析为 string else 将分配空字符串。

      【讨论】:

        猜你喜欢
        • 2012-02-18
        • 2014-12-02
        • 2022-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多