2014-07-17 54 views
0

我已經創建了一個CRM插件,應該從一個子網格上的實體獲取值並保持運行總數。一切似乎正常工作,除了我正在查看的窗體上的字段沒有被更新。當我取消對service.Update(實體)的調用時,它會給我一個無限循環。任何想法,我做錯了什麼?到目前爲止,我看到的所有內容似乎都表明我的代碼是正確的,所以我不知所措。謝謝。CRM 2013插件不更新我的領域

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

發現問題後一點谷歌搜索。我添加了:

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

上下文被實例化後。取消註釋service.Update(entity)之後,它的工作就像一個魅力。

0

你必須小心Context.Deph驗證。

使用深度屬性時必須小心,因爲您可能遇到更復雜的場景。例如,數據導入可能會觸發工作流程來更新成員的「全名」,然後該成員將執行我們的插件。在這種情況下,在插件的第一次執行時,深度將爲3。如果您將上面的代碼片段保持不變,則插件邏輯將永遠不會執行。 - >http://roscode.wordpress.com/2013/04/24/crm-2011-plugins-avoiding-infinite-loops/

其他解決方案是:

  1. 不要使用目標實體進行更新。在代碼中構建一個新的實體對象,只填寫您需要的字段並過濾將在插件註冊工具中觸發更新的屬性。

  2. 在Pre-Step中註冊您的插件並寫入屬性以直接更新到目標中。無需更新。