C# 记录创建的实时工作流在记录提交到数据库之前运行

C# 记录创建的实时工作流在记录提交到数据库之前运行,c#,.net,dynamics-crm,dynamics-crm-2016,C#,.net,Dynamics Crm,Dynamics Crm 2016,我有这段代码,它在记录创建的实时工作流中运行。它基本上确定它在哪个实体上运行,尝试获取“related to”字段,该字段可以从一个实体更改为另一个实体,然后查看相关记录是否是一个帐户,如果是,则更新帐户的一些属性 public override void ExecuteWorkflowLogic(XrmObjects xrmObjects) { using (XrmServiceContext ctx = new XrmServiceContext(xrmObjects.Service

我有这段代码,它在记录创建的实时工作流中运行。它基本上确定它在哪个实体上运行,尝试获取“related to”字段,该字段可以从一个实体更改为另一个实体,然后查看相关记录是否是一个帐户,如果是,则更新帐户的一些属性

public override void ExecuteWorkflowLogic(XrmObjects xrmObjects)
{
    using (XrmServiceContext ctx = new XrmServiceContext(xrmObjects.Service))
    {
        var target = xrmObjects.WorkflowContext.InputParameters["Target"] as Entity;
        Xrm.Account account = null;
        var regardingFieldName = string.Empty;

        var logicalName = string.Empty;
        var primaryKeyName = string.Empty;

        switch (target.LogicalName)
        {
            case Xrm.Task.EntityLogicalName:
            case Xrm.Email.EntityLogicalName:
            case Xrm.PhoneCall.EntityLogicalName:
            case Xrm.Letter.EntityLogicalName:
            case Xrm.Appointment.EntityLogicalName:
            case Xrm.Fax.EntityLogicalName:
                regardingFieldName = "regardingobjectid";
                logicalName = Xrm.ActivityPointer.EntityLogicalName;
                primaryKeyName = "activityid";
                break;
            case Xrm.Annotation.EntityLogicalName:
                logicalName = Xrm.Annotation.EntityLogicalName;
                regardingFieldName = "objectid";
                primaryKeyName = "annotationid";
                break;
            case Xrm.Opportunity.EntityLogicalName:
                regardingFieldName = "customerid";
                logicalName = Xrm.Opportunity.EntityLogicalName;
                primaryKeyName = "opportunityid";
                break;
            case Xrm.Post.EntityLogicalName:
                regardingFieldName = "regardingobjectid";
                logicalName = Xrm.Post.EntityLogicalName;
                primaryKeyName = "postid";
                break;
         }


         var activity = (from a in ctx.CreateQuery(logicalName)
                                where a[regardingFieldName] != null && (Guid)a[primaryKeyName] == target.Id
                                select a).FirstOrDefault();

         var ec = (EntityReference)activity[regardingFieldName];

         if (ec == null)
             return;

         //if regarding isn't an account...
         if (ec.LogicalName != Xrm.Account.EntityLogicalName)
             return;

         account = ctx.AccountSet.SingleOrDefault(x => x.Id == ec.Id);

         if (account == null)
             return;

         account.new_last_activity_created_by = (EntityReference)target["createdby"];
         account.new_last_activity_date = (DateTime)target["createdon"];
         account.new_last_activity_type = GetActivityType(target); //returns an optionset based on entity logical name....
         account.new_last_activity_entity_logicalname = target.LogicalName;

         if (!ctx.IsAttached(account))
              ctx.Attach(account);

         ctx.UpdateObject(account);
         ctx.SaveChanges();
    }
}
我希望它在实时工作流中运行,因为更改将是即时的,而且,因为上面创建实体的用户可能没有更新帐户的权限,因此实时工作流允许我作为具有更新权限的另一个用户(工作流所有者)进行更新

问题是当它是一个活动实体(switch语句中的第一个大块)时,记录看起来好像没有提交到数据库,我无法获取它并进一步查看它(
activity
最终为空)

如果我在
ActivityPointerBase
TaskBase
EmailBase
等中查找
target
的GUID,那么在执行此工作流期间(我假设是在创建记录之后发生的)我在任何地方都看不到它

如果我在异步工作流中运行它,它将适用于所有实体

在实时模式下,它只适用于Opportunity、Post和Annotation。我正在测试中从社交提要菜单创建活动

上面的代码在扩展
BaseWorkflowStep
的类中的方法中运行:

public abstract class BaseWorkflowStep : CodeActivity
{
    protected override void Execute(CodeActivityContext context)
    {
        var xrmObjects = new XrmObjects();

        var serviceFactory = context.GetExtension<IOrganizationServiceFactory>();
        xrmObjects.CodeActivityContext = context;
        xrmObjects.TracingService = context.GetExtension<ITracingService>();
        xrmObjects.WorkflowContext = context.GetExtension<IWorkflowContext>();
        xrmObjects.Service = serviceFactory.CreateOrganizationService(xrmObjects.WorkflowContext.UserId);

        ExecuteWorkflowLogic(xrmObjects);
    }

    public virtual void ExecuteWorkflowLogic(XrmObjects xrmObjects)
    {
        throw new NotImplementedException();
    }
}
公共抽象类BaseWorkflowStep:CodeActivity
{
受保护的覆盖无效执行(CodeActivityContext上下文)
{
var xrobjects=新的xrobjects();
var serviceFactory=context.GetExtension();
xrobjects.CodeActivityContext=上下文;
xrobjects.TracingService=context.GetExtension();
xrobjects.WorkflowContext=context.GetExtension();
xrobjects.Service=serviceFactory.CreateOrganizationService(xrobjects.WorkflowContext.UserId);
ExecuteWorkflowLogic(XRObject);
}
公共虚拟void ExecuteWorkflowLogic(XRObjects XRObjects)
{
抛出新的NotImplementedException();
}
}

这里发生了什么?

现在这可能太旧了,但是如果您使用的是实时工作流(RTWF),那么在WF运行时,记录还不会提交。这部分是因为如果RTWF失败,则失败将取消主记录的创建。因此,主记录和代码结果是同一个DB事务的一部分。这就是为什么async也可以工作的原因,因为这些操作发生在单独的DB事务中。
与其查询数据,不如使用在上下文中传递的图像。例如,如果这是在创建记录之后发生的,您可能会在PostEntityImage集合中使用“PostBusinessEntity”。

如何创建或获取
XRObject.Service
实例?@HenkvanBoeijen我编辑了我的问题。不相关,但是您可以将
ExecuteWorkflowLogic
作为
抽象方法,而不是默认实现引发异常的
虚拟方法。您是否尝试过将这一大块活动分解为每个活动的不同类型并分别查询它们?是的,我知道您应该能够针对ActivityPointInter为所有这些代码创建一个查询,但是首先要让代码正常工作,然后再让它变得漂亮。