2016-10-06 2 views
1

В следующем фрагменте кода я извлекаю заметки, относящиеся к заказу. Он отлично работает, только если notetext содержит данные. Теперь, во время отладки, я обнаружил, что в другом случае это исключает исключение Object reference not set to an instance of an object.Entity.Contains (AttributeName) работает для всех полей аннотаций, но не работает для notetext

Я думаю, что следующий фрагмент выглядит хорошо, но не уверен, чего не хватает, любая идея решить проблему?

private void fetchDocument(IOrganizationService service, Guid vOrderId) 
{ 
    EntityCollection results = null; 
    string tempNote = string.Empty; 
    string tempFileName = string.Empty; 

    ColumnSet cols = new ColumnSet("subject", "filename", "documentbody", "mimetype","notetext"); 
    QueryExpression query = new QueryExpression { 
      EntityName = "annotation" , 
      ColumnSet = cols, 
      Criteria = new FilterExpression 
      { 
       Conditions = { 
       new ConditionExpression("objectid",ConditionOperator.Equal,vOrderId) 
      } 
      } 
      }; 
    results = service.RetrieveMultiple(query); 
    Entity defaultRecord = results.Entities.ElementAtOrDefault(0); 

    if(defaultRecord.Contains("notetext")) 
    { 
     tempNote = defaultRecord.GetAttributeValue<string>("notetext"); 
    } 

    if (defaultRecord.Contains("filename")) 
    { 
     tempFileName = defaultRecord.GetAttributeValue<string>("filename"); 
    }  
} 
+0

Что линия является вашим Null Ссылка ошибки или какой объект нулевой? – Daryl

+0

Здесь вызывается excpetion "if (defaultRecord.Contains (" notetext "))" –

ответ

1

Ваш вопрос на самом деле в этой строке:

Entity defaultRecord = results.Entities.ElementAtOrDefault(0); 

Там нет результатов не найдено, а это означает

нет аннотаций, которая существует с ObjectID из "vOrderId", или пользователь, выполняющий запрос, не имеет прав на чтение этой записи.

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

Эта проверка нуль является обычным явлением, поэтому я написал этот метод расширения:

public Entity GetFirstOrDefault(this IOrganizationService service, QueryBase qb) { 
    return service.RetrieveMultiple(qb)?.Entities.FirstOrDefault(); 
} 

Это позволит упростить ваш код следующим образом:

private void fetchDocument(IOrganizationService service, Guid vOrderId) 
{ 
    EntityCollection results = null; 
    string tempNote = string.Empty; 
    string tempFileName = string.Empty; 

    ColumnSet cols = new ColumnSet("subject", "filename", "documentbody", "mimetype","notetext"); 
    QueryExpression query = new QueryExpression { 
      EntityName = "annotation" , 
      ColumnSet = cols, 
      Criteria = new FilterExpression 
      { 
       Conditions = { 
       new ConditionExpression("objectid",ConditionOperator.Equal,vOrderId) 
      } 
      } 
      }; 

    var defaultRecord = service.GetFirstOrDefault(query); 
    if(defaultRecord != null) 
    { 
     if(defaultRecord.Contains("notetext")) 
     { 
      tempNote = defaultRecord.GetAttributeValue<string>("notetext"); 
     } 

     if (defaultRecord.Contains("filename")) 
     { 
      tempFileName = defaultRecord.GetAttributeValue<string>("filename"); 
     } 
    } 
} 
2

Вы не охраняются defaultrecord нет.

results = service.RetrieveMultiple(query); 
if (results.Entities == null || !results.Entities.Any()) return; 
Entity defaultRecord = results.Entities.ElementAt(0); 

Продление ответа на резервную копию result.Entities == null check.

Извлечь несколько EntityCollection не является надежным.

EntityCollection недвижимость:

Decomplied SDK получить несколько ядро:

protected internal virtual EntityCollection RetrieveMultipleCore(QueryBase query) 
    { 
     bool? retry = new bool?(); 
     do 
     { 
     bool forceClose = false; 
     try 
     { 
      using (new OrganizationServiceContextInitializer(this)) 
      return this.ServiceChannel.Channel.RetrieveMultiple(query); 
     } 
     catch (MessageSecurityException ex) 
     { 
      .. 
     } 
     finally 
     { 
      this.CloseChannel(forceClose); 
     } 
     } 
     while (retry.HasValue && retry.Value); 
     return (EntityCollection) null; 
    } 

Decomplied SDK Cached Организация Serivce Контекст получить несколько:

public override EntityCollection RetrieveMultiple(QueryBase query) 
{ 
    RetrieveMultipleRequest retrieveMultipleRequest = new  RetrieveMultipleRequest(); 
    retrieveMultipleRequest.Query = query; 
    RetrieveMultipleResponse multipleResponse = this.Execute<RetrieveMultipleResponse>((OrganizationRequest) retrieveMultipleRequest); 
    if (multipleResponse == null) 
    return (EntityCollection) null; 
    else 
    return multipleResponse.EntityCollection; 
} 


public EntityCollection EntityCollection 
{ 
    get 
    { 
    if (this.Results.Contains("EntityCollection")) 
     return (EntityCollection) this.Results["EntityCollection"]; 
    else 
     return (EntityCollection) null; 
    } 
} 
+0

'Results.Entities' никогда не будет' null'. Нет причин проверять это. Кроме того, добавление «Any' check - это просто дополнительный шаг, когда' defaultRecord' не равен null. Лучше просто восстановить «defaultRecord» с помощью «ElementAtOrDefault» и проверить, что значение defaultRecord равно null. Наконец ИМХО заявление «если» с «!» что «нет» целое утверждение менее читаемо, чем «! =» – Daryl

+0

@Daryl, любая документация для поддержки вашего оператора 'Result.Entities никогда не будет пустым'? Я не вижу ничего упомянутого здесь https://msdn.microsoft.com/en-us/library/microsoft.xrm.sdk.messages.retrievemultipleresponse.aspx. Я предпочел бы быть в безопасности с SDK/API, с которыми я не владею, и выполнить дополнительную проверку. '.Any()' будет иметь значение только при ленивой загрузке данных, поскольку она будет извлекать данные и перебирать элементы и возвращать bool, если элемент найден. Это то же самое, что и проверка, если elementordefault имеет значение null. Насколько менее читаемо, что '! Any()' более читается, чем 'All()'. – dynamicallyCRM

+0

Когда вы смотрите на разрозненный исходный код для SDK, вы можете видеть, что он его устанавливает. Кроме того, свойство 'Entities' является readonly, а это означает, что им нужно создать экземпляр свойства в конструкторе, поскольку они не выставляют метод« Добавить »или метод для его экземпляра в противном случае. – Daryl