4

如何使用crm 2011 sdk和XrmServiceContext创建交易?CRM 2011 SDK交易

下一个例子'new_brand'是一些自定义实体。我想创造三个品牌。第三个有错误的OwnerID guid。当我调用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(); 
} 
+0

你会得到什么异常? – glosrob

+0

好点@glosrob,我推测这个例外不是问题,而是需要回滚。我怀疑这个例外是因为没有这样的SystemUser,它的id为'new Guid(“00000000-0000-0000-0000-000000000000”);'。拉撒路 - 如果异常得到解决,仍然需要知道如何回滚? –

+1

@Greg:是的,但我认为这个问题仍然具有学术价值,即使问题被回答了@ [MSDN](http://social.microsoft.com/Forums/en/crmdevelopment/thread/229dec17-6c49-43ad -9751-6ea61e4ecd36)。 –

回答

1

是否有可能不使用插件和工作流程?

不,我不相信它是。每个context.AddObject()是原子的。如果您不想使用插件,那么我认为您可以执行的操作有一些清理逻辑,如果您的条件未得到满足,则会删除创建的记录。

+0

感谢您的回答。 工作流事务操作?我认为它不支持回滚操作? – lazarus

+0

@lazarus:我不相信它,但会[[]](http://stackoverflow.com/a/5093860/684271)的问题[从功能区JScript CRM Online 2011调用C#代码]( http://stackoverflow.com/questions/5091565)满足您的需求? –

2

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); 
     } 
    } 
} 
2

其实这是可能不使用插件。

您可以使用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