0

我最近开始在 Execute 方法中获取 CRM 对象,并在单独的方法中执行插件/工作流业务逻辑。
这种方法可以改进(或丢弃)吗?
使用 LINQ 获取工作流的目标记录是否可以接受?
比输入参数方便;工作流也是异步的,不会影响用户体验。

对于插件:

    public class AddEmailAttachments : IPlugin
    {
        private void AddAttachments(Entity target, IOrganizationService service, Context linq)
        {
            // Business logic
        }
        /*
         * Get all the Objects that we need
         * and call AddAttachments
         * */
        public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = null;
            IOrganizationServiceFactory factory = null;
            IOrganizationService service = null;
            Entity target = null;
            Context linq = null;
            try // and get the services we need
            {
                context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
                factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                service = factory.CreateOrganizationService(context.UserId);
                target = (Entity)context.InputParameters["Target"];
                linq = new Context(service);
                if (service != null && target != null && linq != null)
                    AddAttachments(target, service, linq);
            }
            catch (Exception) { }; // this is strict because if this plugin fails then the email will not be created in CRM and disrupt the business process

        }
    }

对于工作流:

    public class SendCaseNotifications : CodeActivity
    {
        /* Receives the necessary Objects and 
         * Sends the email
         * */
        private void SendNotifications(Incident incident, IOrganizationService service, Email email, Context linq)
        {
            // Perform business logic
        }
        /* Get the Objects that are required and call
         * the method
         * */
        protected override void Execute(CodeActivityContext context)
        {
            IWorkflowContext workflowContext = context.GetExtension<IWorkflowContext>();
            IOrganizationServiceFactory factory = context.GetExtension<IOrganizationServiceFactory>();
            IOrganizationService service = factory.CreateOrganizationService(workflowContext.InitiatingUserId);
            Entity target = workflowContext.InputParameters["Target"] as Entity;
            Incident incident = null;
            Email email = null;
            Context linq = new Context(service);
            IEnumerable<Incident> incidentQuery = from incidents in linq.IncidentSet where incidents.Id.Equals(target.Id) select incidents;
            if (incidentQuery.Any())
                incident = incidentQuery.First();
            if (incident == null)
                throw new InvalidPluginExecutionException("Unable to retrieve Case with id: " + target.Id.ToString() + ". Re-try the operation or contact the system administrator.");
            IEnumerable<Email> emailQuery = from emails in linq.EmailSet where emails.Id.Equals(incident.mda_originatingemail.Id) select emails;
            if (emailQuery.Any())
                email = emailQuery.First();
            if (email == null)
                throw new InvalidPluginExecutionException("Unable to retrieve Email with id: " + incident.mda_originatingemail.Id.ToString() + ". Re-try the operation or contact the system administrator.");
            SendNotifications(incident, service, email, linq);
        }
    }

我在 Execute 中尽可能多地处理异常,然后将对象传递给执行实际工作的方法。
我最近了解到,如果同步插件抛出异常,它会影响业务流程。

4

1 回答 1

2

1 => 这种方法可以改进(或丢弃)吗?

您可以通过几种方式来改善这一点。改进这一点的最大方法是为插件和工作流活动创建一个基类,自动执行所有必要的上下文提取、组织服务等。您甚至可以更进一步,为创建/创建基类Update/Delete/SetState/etc 插件适当地提取输入和输出参数。

其次,如果您想进行完整的 OO 设计,您可以将所有业务逻辑放在单独的类而不是函数中。如果您想要进行单元测试,它将更少耦合,更有组织地处理复杂的逻辑,并且可测试。

2 => 用 LINQ 获取工作流的目标记录是否可以接受?

我认为问题是使用 LINQ 检索工作流的当前记录是一种好习惯吗?你的做法没有任何问题。您可能只使用 LINQ 扩展方法FirstOrDefault()而不是Any()and First()

此外,通常情况下,Crm Retrieves 最好只返回您需要的列。虽然您可能不会在检索一条记录时注意到这一点,但如果您要检索多条记录,则绝对应该这样做。

于 2013-06-11T00:15:52.977 回答