CRM 2013插件不更新我的字段

时间:2014-07-17 17:03:18

标签: c# plugins dynamics-crm

我已经创建了一个CRM插件,该插件应该从子网格上的实体中获取值并保持运行总计。一切似乎都正常工作,除了我看到的表格上的字段没有被更新。当我取消注释对service.Update(实体)的调用时,它给了我一个无限循环。关于我做错了什么的任何想法?到目前为止,我所看到的所有内容似乎都表明我的代码是正确的,所以我不知所措。谢谢。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Activities;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Workflow;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Messages;

namespace SubGrid_Calculator
{
public class SubgridCalculator : IPlugin
{
    //A list is a data structure that preserves the order of the elements that are put into it. 
    //A set is a data structure that does not allow duplicate objects. Order is NOT guaranteed in a set.
    //EntityReference returns 3 properties: Logical Name, ID and Name (often, but not always the primary key)

    IEnumerable<Entity> GetRelatedEntities(IOrganizationService service, string primaryEntity, Guid primaryEntityId, string relationshipName, string targetEntity)
    {
        //the related entity we are going to retrieve
        QueryExpression query = new QueryExpression();
        query.EntityName = targetEntity;
        query.ColumnSet = new ColumnSet("new_totalmonthlytext", "crmp_contract", "crmp_name");

        //the relationship that links the primary to the target
        Relationship relationship = new Relationship(relationshipName);
        relationship.PrimaryEntityRole = EntityRole.Referenced; //important if the relationship is self-referencing

        //the query collection which forms the request
        RelationshipQueryCollection relatedEntity = new RelationshipQueryCollection();
        relatedEntity.Add(relationship, query);

        //the request to get the primary entity with the related records
        RetrieveRequest request = new RetrieveRequest();
        request.RelatedEntitiesQuery = relatedEntity;
        request.ColumnSet = new ColumnSet("crmp_name");
        request.Target = new EntityReference(primaryEntity, primaryEntityId);

        RetrieveResponse r = (RetrieveResponse)service.Execute(request); //was service.Execute

        //query the returned collection for the target entity ids
        return r.Entity.RelatedEntities[relationship].Entities;//.Select(e => e.Id);
    }     

    private IOrganizationService orgService;
    private TraceServiceWrapper tracingService;

    public void Execute(IServiceProvider serviceProvider)
    {
        //Activity code
        Microsoft.Xrm.Sdk.IPluginExecutionContext context = (Microsoft.Xrm.Sdk.IPluginExecutionContext)
         serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext));

        IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
        IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
        this.orgService = serviceFactory.CreateOrganizationService(context.UserId);
        OrganizationServiceContext ServiceContext = new OrganizationServiceContext(service);

        // The trace wrapper is a CRMPoint.net custom library for maching logging and tracing
        //TraceServiceWrapper trace = new TraceServiceWrapper(service, tracingService, "HttpTest"); NO idea what I'd need as my middle arg
        ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));             //localContext.TracingService;

        var crmTracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

        if (crmTracingService == null)
        {
            throw new InvalidPluginExecutionException("Failed to retrieve the tracing service.");
        }
        this.tracingService = new TraceServiceWrapper(this.orgService, crmTracingService, "SubgridCalculator");


        if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
        {
            // Obtain the target entity from the input parameters.
            Entity entity = (Entity)context.InputParameters["Target"];

            this.tracingService.Trace("Plugin Started!");
            this.tracingService.Trace("MEssage Name: ", context.MessageName);
            this.tracingService.Trace("Primary Entity Name: ", context.PrimaryEntityName);
            this.tracingService.Trace("Primary Entity Id: ", context.PrimaryEntityId );
            this.tracingService.Trace("PluginExecutionContext: ", context);
            this.tracingService.Trace("Post Context:");
            //this.tracingService.Trace(" ", );

            // Verify that the target entity represents an HttpTest entity
            if (entity.LogicalName != "crmp_contract") //was new_httptest
                return;
            this.tracingService.Trace("Entity is Plan:");

            //var preEntityImage = context.PreEntityImages["PreImage"];
            //this.tracingService.Trace("Preimage:", preEntityImage);
            //this.tracingService.Trace(TracingItemType.PreImage, EntityTraceHelper.TraceAttributes(preEntityImage));

            //var postEntityImage = context.PostEntityImages["PostImage"];
            //this.tracingService.Trace("POSTimage:", postEntityImage);
            //this.tracingService.Trace(TracingItemType.PostImage, EntityTraceHelper.TraceAttributes(postEntityImage));
            //subgrid_ratedescriptordetail
            //crmp_contract_crmp_ratedescriptorsetdetail_Contract
            //crmp_policy for policy   crmp_contract for plan
            //crmp_ratedescriptorsetdetail for rdd

            List<Entity> results = GetRelatedEntities(service, "crmp_contract", entity.Id, "crmp_contract_crmp_ratedescriptorsetdetail_Contract", 
                "crmp_ratedescriptorsetdetail").ToList();

            decimal total = 0.000M;
            this.tracingService.Trace("About to calculate total:");
            foreach(Entity e in results)
            {
                total += Convert.ToDecimal(e["new_totalmonthlytext"]);
                Console.WriteLine(e["new_totalmonthlytext"]);
                this.tracingService.Trace(e["new_totalmonthlytext"].ToString());
            }
            this.tracingService.Trace("Total finished.");
            try
            {
                //total = total / 0;
                //entity.Attributes.Add("new_totalmonthlycostthree", total);
                this.tracingService.Trace("About to set total.");
                //entity["new_totalmonthlycostthree"] = total;
                entity.Attributes["new_totalmonthlycostthree"] = total;
                this.tracingService.Trace("Total: ", entity["new_totalmonthlycostthree"].ToString());
                this.tracingService.Trace("Total set. Abut to update.");
                this.tracingService.Trace("Entity: ", entity);
                //service.Update(entity);
                this.tracingService.Trace("Updated. About to handle success");
                this.tracingService.HandleSuccess();
                this.tracingService.Trace("Success Handled!");
            }
            catch (Exception ex)
            {
                this.tracingService.HandleException(ex);
                throw new InvalidPluginExecutionException(ex.Message + " - Something went wrong.");
            }
        }
    }
}
}

2 个答案:

答案 0 :(得分:0)

通过谷歌搜索后发现问题。我补充说:

if (context.Depth > 1) { return; }

在实例化上下文之后。在取消注释service.Update(entity);之后,它就像一个魅力。

答案 1 :(得分:0)

你必须小心Context.Deph验证。

  

使用Depth属性时必须小心,因为您可能遇到更复杂的场景。例如,数据导入可能会触发工作流程来更新成员的“全名”,而成员又会执行我们的插件。在这种情况下,插件第一次执行时Depth将为3。如果您将代码片段保持不变,则插件逻辑将永远不会被执行。    - &GT; http://roscode.wordpress.com/2013/04/24/crm-2011-plugins-avoiding-infinite-loops/

其他解决方案将是:

  1. 请勿使用目标实体进行更新。在代码中构建一个新的Entity对象,只填写您需要的字段,并过滤将在pluginregistration工具中触发更新的属性。

  2. 在Pre-Step中注册插件并编写属性以直接更新到目标中。无需更新。