2016-04-21 2 views
2

В настоящее время я разрабатываю MS Dynamics CRM 2013 - плагин. Когда я пытаюсь присвоить строковое значение ключу поля объекта, он дает мне исключение «keynotfound».'Данный ключ отсутствовал в словаре' - но существует ключ

Это оставляет меня невежественным, потому что я могу проверить, что ключ существует. Ключ, который я даю, также написан правильно, и типы данных также совместимы.

Вот некоторые дополнительные сведения:

  • Я пытался решить вопрос с перезагрузкой сервера. Ничего.
  • Удаленная отладка не является вариантом.
  • Я поменял «retrieved.EntityCollection.Entities [i] [forField]» с retrieved.EntityCollection.Entities [i] ["new_name"], и все работало нормально (например, указывая на очевидное здесь, но "new_name" не является ключом, к которому я пытаюсь обратиться).
  • Выполнение останавливается @ "если (retrieved.EntityCollection.Entities [я] [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()); 
    } 
} 

ответ

2

При запросе данных в Dynamics CRM, важно знать, что поля записи, имеющие null значения в базе данных не включены в Attributes коллекции Entity экземпляров возвращаются.

Получение значения из Entity «s Attribute с этой конструкцией:

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

преуспевает, когда атрибут forField уже имеет значение в базе данных, но терпит неудачу когда его текущее значение null.

Поэтому предпочтительный метод для получения значений атрибутов от сущности является GetAttributeValue<T>, как это:

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

Этого метод возвращает значение, когда атрибут существует в коллекции атрибутов, в противном случае она возвращает null.

2

Как вы подтвердили, что ключ существует?

Если данные в поле является пустым экземпляр Entity не будет содержать что ключевой, даже если вы укажете его в ColumnSet запроса.

Это вернет вам логическое значение, указывающее, существует ли ключ в объекте. Вы можете сделать это, прежде чем пытаться прочитать атрибут.

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

Приведенный ниже элемент управления приведет к исключению, которое вы получаете, если поле равно null. Просто убедитесь, что атрибут существует раньше.

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

Кроме того, вы получите нулевое ссылочное исключение, если записи не были возвращены из запроса. Заставьте вас выполнить нулевую проверку на retrieved.EntityCollection.Entities.

+1

Я бы не советовал проверить, действительно ли коллекция атрибутов содержит определенный член. Предпочтительным методом является использование метода GetAttribute . Кроме того, всегда присутствует символ DataCollection ', возвращаемый' IOrganizationService.RetrieveMultiple' (например, в 'retrieved.EntyCollection.Entities'), поэтому там также не нужна проверка« null ». –

+0

Вы правы, сущности никогда не являются нулевыми. – tdgtyugdyugdrugdr

1

Если какой-либо из полей среди (new_forfield, new_prefix, new_postfix, new_separator) имеет нулевое значение, этот столбец не присутствует в извлеченном объекте, и вы пытаетесь получить значение нулевого столбца preImageEntity [ "new_forfield"], который бросит keynotfound'-исключение,
так изменить код

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

это будет проверять поле, если он существует, чем будет анализировать значение строки еще присвоит пустую строку.

Смежные вопросы