我已经创建了一个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.");
}
}
}
}
}
答案 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/
其他解决方案将是:
请勿使用目标实体进行更新。在代码中构建一个新的Entity对象,只填写您需要的字段,并过滤将在pluginregistration工具中触发更新的属性。
在Pre-Step中注册插件并编写属性以直接更新到目标中。无需更新。