CRM 2011 SDK транзакция

Как создать транзакцию, используя crm 2011 sdk и XrmServiceContext?

В следующем примере "new_brand" - это некоторая пользовательская сущность. Я хочу создать три бренда. Третье имеет неправильный идентификатор OwnerID Когда я вызываю метод SaveChanges(), создаются два бренда, и у меня есть исключение. Как откатить создание первых двух брендов?

Возможно ли это без использования плагинов и рабочих процессов?

using (var context = new XrmServiceContext(connection))
{
    SystemUser owner = context.SystemUserSet.FirstOrDefault(s => s.Id == new Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"));

    // create 3 brands
    new_brand b1 = new new_brand();
    b1.new_brandidentification = 200;
    b1.new_name = "BRAND 200";
    b1.OwnerId = owner.ToEntityReference();
    context.AddObject(b1);

    new_brand b2 = new new_brand();
    b2.new_brandidentification = 300;
    b2.new_name = "BRAND 300";
    b2.OwnerId = owner.ToEntityReference();
    context.AddObject(b2);

    new_brand b3 = new new_brand();
    b3.new_brandidentification = 400;
    b3.new_name = "BRAND 400";
    b3.OwnerId = new EntityReference(SystemUser.EntityLogicalName, new Guid("00000000-0000-0000-0000-000000000000"));
    context.AddObject(b3);

    context.SaveChanges();
}

3 ответа

Решение

Возможно ли это без использования плагинов и рабочих процессов?

Нет, я не верю, что это так. каждый context.AddObject() атомно. Если вы не хотите использовать плагины, то все, что я думаю, вы можете сделать, это иметь какую-то логику очистки, которая удаляет созданные записи, если ваши условия не выполняются.

На самом деле это возможно без использования плагинов.

Вы можете использовать ссылки отношений CRM для принудительного поведения транзакций:

EntityA primaryEntity = new EntityA() { //initialise me... };
EntityB secondaryEntity = new EntityB() { //initialise me... };

context.AddObject(primaryEntity);
context.AddObject(secondaryEntity);

// This is the key part: explicitly link the two entities
context.AddLink(primaryEntity, 
    new Relationship("relationship_name_here"), secondaryEntity);

// commit changes to CRM
context.SaveChanges();

У этого подхода есть несколько недостатков:

  • Очевидно, что в CRM должны существовать отношения между двумя сущностями. Если нет никаких отношений, вам придется пойти с плагином.
  • Лично я считаю, что код может стать грязным, если вам нужно сохранить большую иерархию объектов за один раз.

Альтернативный подход может заключаться в рассмотрении реализации шаблона команды с использованием плагинов.

Идея состоит в том, что вы создаете объекты CRM на клиенте, сериализуете их и передаете их в CRM через пользовательский объект. Предварительно созданный плагин затем настраивается на эту сущность для сериализации и создания объектов в рамках транзакции плагина.

Отличный пост в блоге, описывающий обе стратегии, можно найти здесь: http://crm.davidyack.com/journal/2012/6/26/crm-client-extension-data-access-strategies.html

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

Самый простой способ реализовать такую ​​логику - добавить новое поле к new_Brand с именем new_TransactionGroupId и использовать его для удаления любых записей, которые были созданы следующим образом:

using (var context = new XrmServiceContext(connection))
{
    SystemUser owner = context.SystemUserSet.FirstOrDefault(s => s.Id == new Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"));
    var transactionGroupId = Guid.NewGuid();

    // create 3 brands
    new_brand b1 = new new_brand();
    b1.new_brandidentification = 200;
    b1.new_name = "BRAND 200";
    b1.OwnerId = owner.ToEntityReference();
    b1.new_TransactionGroupId = transactionGroupId ;
    context.AddObject(b1);

    new_brand b2 = new new_brand();
    b2.new_brandidentification = 300;
    b2.new_name = "BRAND 300";
    b2.OwnerId = owner.ToEntityReference();
    b2.new_TransactionGroupId = transactionGroupId ;
    context.AddObject(b2);

    new_brand b3 = new new_brand();
    b3.new_brandidentification = 400;
    b3.new_name = "BRAND 400";
    b3.OwnerId = new EntityReference(SystemUser.EntityLogicalName, new Guid("00000000-0000-0000-0000-000000000000"));
    b3.new_TransactionGroupId = transactionGroupId;
    context.AddObject(b3);

    try{
        context.SaveChanges();
    } catch (Exception ex){
        // Since one brand failed, cleanup all brands
        foreach(brand in context.new_brand.where(b => b.new_TransactionGroupId == transactionGroupId)){
            context.Delete(brand);
        }
    }
}
Другие вопросы по тегам