Безопасны ли API-интерфейсы ранней привязки CRM 2011 для использования с библиотекой Task Parallel?

#c#-4.0 #dynamics-crm-2011 #task-parallel-library

#c #-4.0 #dynamics-crm-2011 #task-parallel-library

Вопрос:

Я испытываю прерывистое исключение SaveChangesException при создании объектов CRM с использованием API-интерфейсов ранней привязки (сгенерированный контекст) через Threading.Task.

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

Как вы можете видеть, в моем коде нет общего состояния, я создаю соединение CRM, службу и контекст для каждой операции.

Генерируется исключение:

Microsoft.Xrm.Sdk.SaveChangesException: при обработке этого запроса произошла ошибка. —> Система.Исключение ArgumentOutOfRangeException: индекс был вне диапазона. Должно быть неотрицательным и меньше размера коллекции. Имя параметра: индекс

Я что-то здесь упускаю или ранние привязанные классы SDK небезопасны для использования в многопоточной среде?

 class Program
    {
        static void Main(string[] args)
        {
            foreach (var index in Enumerable.Range(1, 400))
            {
                var capturedIndex = index;
                Task.Factory.StartNew(() => CreateContact(capturedIndex));
            }

            Console.Read();
        }

        private static void CreateContact(int i)
        {
            var contact = new Contact {FirstName = "Test", LastName = string.Concat("Contact_", i)};
            var context = new XrmServiceContext(new OrganizationService(new CrmConnection("Crm")));  // The generated context is taken from the SDK samples
            context.AddObject(contact);

            try
            {
                context.SaveChanges();
                Console.WriteLine(string.Concat("Contact created - ", i));
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);            
            }
        }
    }
  

Комментарии:

1. Я случайно заметил подобную странность при использовании Parallel. Для консольного приложения, но я просто использовал объект Entity с поздней привязкой. Мой код выглядел очень похожим, но использует OrganizationService . Создать метод. Очень странно!

2. Что касается контекстов, у вас должен быть один для каждой задачи / потока. У меня нет ответа, но может ли это быть ограничением веб-службы организации (например, maxconcurrentcalls от wcf?)

3. Есть ли что-нибудь еще для трассировки стека в исключении?

Ответ №1:

Исключение возникает на более низком уровне в конфигурации WCF. Для тех, кто использует объекты с поздней привязкой, обходным путем является отключение свойства ProxyTypesEnabled в CrmConnection. Другим обходным путем является установка ServiceConfigurationMode на PerInstance, но, к сожалению, это приводит к снижению производительности. Примечание: оба они также могут быть установлены через строку подключения.

 var connection1 = new CrmConnection("Crm")
{
    ProxyTypesEnabled = false
}; // late-bound only

var connection2 = new CrmConnection("Crm")
{
    ServiceConfigurationInstanceMode = ServiceConfigurationInstanceMode.PerInstance
};