#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
};