CRM 2011 SDK事务

CRM 2011 SDK事务,sdk,transactions,dynamics-crm-2011,transactionscope,early-binding,Sdk,Transactions,Dynamics Crm 2011,Transactionscope,Early Binding,如何使用crm 2011 sdk和XrmServiceContext创建事务 在下一个示例中,“新品牌”是一些定制实体。我想创建三个品牌。第三个具有错误的所有者ID guid。当我调用SaveChanges()方法时,创建了两个品牌,我得到了一个异常。如何回滚前两个品牌的创建 是否可以不使用插件和工作流 使用(var context=new XrmServiceContext(连接)) { SystemUser owner=context.SystemUserSet.FirstOrDefault

如何使用crm 2011 sdk和XrmServiceContext创建事务

在下一个示例中,“新品牌”是一些定制实体。我想创建三个品牌。第三个具有错误的所有者ID guid。当我调用SaveChanges()方法时,创建了两个品牌,我得到了一个异常。如何回滚前两个品牌的创建

是否可以不使用插件和工作流

使用(var context=new XrmServiceContext(连接))
{
SystemUser owner=context.SystemUserSet.FirstOrDefault(s=>s.Id==新Guid(“XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXX”);
//创建3个品牌
新品牌b1=新品牌();
b1.新品牌标识=200;
b1.new_name=“品牌200”;
b1.OwnerId=owner.ToEntityReference();
AddObject(b1);
新品牌b2=新品牌();
b2.新品牌标识=300;
b2.new_name=“品牌300”;
b2.OwnerId=owner.ToEntityReference();
AddObject(b2);
新品牌b3=新品牌();
b3.新品牌标识=400;
b3.new_name=“品牌400”;
b3.OwnerId=新的EntityReference(SystemUser.EntityLogicalName,新Guid(“00000000-0000-0000-0000-0000-000000000000”);
AddObject(b3);
SaveChanges();
}
是否可以不使用插件和工作流


不,我不相信是这样。每个
context.AddObject()
都是原子的。如果您不想使用插件,那么我认为您所能做的就是使用某种清理逻辑,在您的条件不满足时删除创建的记录。

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

实际上,这不需要使用插件就可以实现

您可以使用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。然后在此实体上设置预创建插件,以反序列化并在插件事务范围内创建对象


在这里可以找到一篇描述这两种策略的优秀博文:

你得到了什么异常?很好@glosrob,我认为异常不是问题,而是需要回滚。我怀疑例外情况是因为没有id为新Guid(“00000000-0000-0000-0000-0000-000000000000”)的系统用户。拉扎勒斯-如果例外情况得到解决,还需要知道如何回退吗?@Greg:是的,但我认为这个问题仍然具有学术价值,即使这个问题得到了回答。谢谢你的回答。工作流是事务性操作吗?我认为它不支持回滚操作?@lazarus:我不相信,但是像这样的问题能满足你的需要吗?