CrmServiceClient не может быть создан - PullRequest
2 голосов
/ 18 июня 2019

У нас есть ситуация, когда класс CrmServiceClient не может быть создан, с ошибкой 'Ссылка на объект не установлена ​​на объект' , исходящей из глубины недр конструктора. Я также получил Коллекция была изменена; Операция перечисления может не выполнить ошибку в некоторых ситуациях.

Это происходит не всегда, но мы, похоже, можем воспроизвести его, когда очень быстро запускаем несколько запросов.

Мы создаем объект следующим образом:

 var ctx = new CrmServiceClient(ConfigurationManager.ConnectionStrings["Xrm"].ConnectionString);

Строка подключения действительна, и мы установили RequireNewInstance в true

Изначально мы использовали ctx в блоке using, но нам сообщили, что не следует избавляться от CrmServiceClient, поэтому мы удалили блок using, но это не решило проблему.

Трассировка стека ниже - я вставил только соответствующую часть. Стек, ведущий к этой точке, может быть любым фрагментом кода, который пытается подключиться к CRM для извлечения данных

   at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
   at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
   at System.Collections.Generic.List`1.Enumerator.MoveNext()
   at Microsoft.Xrm.Tooling.Connector.Utilities.GetOrgnameAndOnlineRegionFromServiceUri(Uri serviceUri, String& onlineRegion, String& organizationName, Boolean& isOnPrem)
   at Microsoft.Xrm.Tooling.Connector.CrmConnection.SetOrgnameAndOnlineRegion(Uri serviceUri)
   at Microsoft.Xrm.Tooling.Connector.CrmConnection..ctor(String serviceUri, String userName, String password, String domain, String homeRealmUri, String authType, String requireNewInstance, String clientId, String redirectUri, String tokenCacheStorePath, String loginPrompt, String certStoreName, String certThumbprint, String skipDiscovery)
   at Microsoft.Xrm.Tooling.Connector.CrmConnection..ctor(IDictionary`2 connection)
   at Microsoft.Xrm.Tooling.Connector.CrmConnection.Parse(String connectionString)
   at Microsoft.Xrm.Tooling.Connector.CrmServiceClient.ConnectToCrmWebService(String crmConnectionString)
   at Microsoft.Xrm.Tooling.Connector.CrmServiceClient..ctor(String crmConnectionString)

1 Ответ

2 голосов
/ 19 июня 2019

Мне кажется, я разобрался с проблемой.Я использовал DotNetPeek, чтобы посмотреть на основной код, который не работал.Статический метод GetOrgnameAndOnlineRegionFromServiceUri был местом, где произошла ошибка.

Я отследил его до статического списка (discoSvcs), для которого было задано значение NULL до возврата метода.Другие потоки, которые вызывают этот метод, также пытаются сделать что-то с этим списком.В итоге возникает условие гонки, при котором один поток может проверить, не является ли он нулевым.

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

Определение статического списка

namespace Microsoft.Xrm.Tooling.Connector
{
  public class Utilities
  {
    private static CrmOnlineDiscoveryServers discoSvcs;
    private static List<string> _autoRetryRetrieveEntityList;

    private Utilities()
    {
    }

Функция задачи

Переменная статического списка проверяется в начале этой функции и, если она пуста, она заполняется некоторыми значениями.Затем он используется позже в методе перед установкой значения null в блоке finally.

  public static void GetOrgnameAndOnlineRegionFromServiceUri(
      Uri serviceUri,
      out string onlineRegion,
      out string organizationName,
      out bool isOnPrem)
    {
      isOnPrem = false;
      onlineRegion = string.Empty;
      organizationName = string.Empty;
      if (serviceUri.Host.ToUpperInvariant().Contains("DYNAMICS.COM") || serviceUri.Host.ToUpperInvariant().Contains("MICROSOFTDYNAMICS.DE") || (serviceUri.Host.ToUpperInvariant().Contains("MICROSOFTDYNAMICS.US") || serviceUri.Host.ToUpperInvariant().Contains("DYNAMICS-INT.COM")))
      {
        if (Utilities.discoSvcs == null)
          Utilities.discoSvcs = new CrmOnlineDiscoveryServers();
        try
        {
          List<string> stringList = new List<string>((IEnumerable<string>) serviceUri.Host.Split(new string[1]
          {
            "."
          }, StringSplitOptions.RemoveEmptyEntries));
          organizationName = stringList[0];
          stringList.RemoveAt(0);
          StringBuilder stringBuilder = new StringBuilder();
          foreach (string str in stringList)
          {
            if (!str.Equals("api"))
              stringBuilder.AppendFormat("{0}.", (object) str);
          }
          string crmKey = stringBuilder.ToString().TrimEnd('.').TrimEnd('/');
          stringBuilder.Clear();
          if (!string.IsNullOrEmpty(crmKey))
          {
            CrmOnlineDiscoveryServer onlineDiscoveryServer = Utilities.discoSvcs.OSDPServers.Where<CrmOnlineDiscoveryServer>((Func<CrmOnlineDiscoveryServer, bool>) (w =>
            {
              if (w.DiscoveryServer != (Uri) null)
                return w.DiscoveryServer.Host.Contains(crmKey);
              return false;
            })).FirstOrDefault<CrmOnlineDiscoveryServer>();
            if (onlineDiscoveryServer != null && !string.IsNullOrEmpty(onlineDiscoveryServer.ShortName))
              onlineRegion = onlineDiscoveryServer.ShortName;
          }
          isOnPrem = false;
        }
        finally
        {
          Utilities.discoSvcs.Dispose();
          Utilities.discoSvcs = (CrmOnlineDiscoveryServers) null;
        }
      }
      else
      {
        isOnPrem = true;
        if (((IEnumerable<string>) serviceUri.Segments).Count<string>() < 2)
          return;
        organizationName = serviceUri.Segments[1].TrimEnd('/');
      }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...