我正在尝试为Dynamics CRM 2013编写一个插件,到目前为止,我无法让它工作。我设法找到了错误。当我调用service.Create(newAppt)并显示错误消息“”无法插入重复的密钥“”时,它似乎崩溃了,我似乎无法追踪到底出了什么问题。代码下面是跟踪程序的完整输出。在过去的三个小时里,我已经多次在msdn上看过这些例子,我似乎无法看到我做错了什么。任何帮助将不胜感激,非常感谢您提前。
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
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.Messages;
using Microsoft.Xrm.Sdk.Query;
namespace NoteCopier
{
public class NoteCopier : CodeActivity
{
//This header is for input parameters. We don't need it.
[Input("Appointment")] //Parameter name //was Annotation
[ReferenceTarget("appointment")] //Parameter type, we usually pass in the entity logical name
public InArgument<EntityReference> Appointment { get; set; }
//This is an entity reference^.
//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)
private object setValueSafely(AttributeCollection collection, string key, object val)
{
if (!collection.ContainsKey(key))
{
collection.Add(key, val);
}
else
{
collection[key] = val;
}
return val;
}
Entity getAppointment(Guid id, IOrganizationService service)
{
/*ColumnSet columns = new ColumnSet("activityid", "actvitytypecode", "description", "location", "requiredattendees", "optionalattendees",
"scheduledstart", "scheduledend", "subject");*/
Entity r = (Entity)service.Retrieve("appointment", id,
new ColumnSet("activitytypecode", "description", "location", "requiredattendees", "optionalattendees",
"scheduledstart", "scheduledend", "subject")); //was service.Execute //also grabbed activityid before
return r;
}
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("objecttypecode", "notetext", "annotationid");
//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("activityid");
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);
}
protected override void Execute(CodeActivityContext executionContext)
{
//Activity code
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
ITracingService tracingService = executionContext.GetExtension<ITracingService>();
TraceServiceWrapper trace = new TraceServiceWrapper(service, tracingService, "ApptNote");
EntityReferenceCollection relatedEntities = new EntityReferenceCollection();
Relationship relationship = new Relationship("Appointment_Annotation");
trace.Trace("Plugin Started!");
trace.Trace("Message Name: ", context.MessageName);
trace.Trace("Primary Entity Name: ", context.PrimaryEntityName);
trace.Trace("Primary Entity Id: ", context.PrimaryEntityId);
trace.Trace("PluginExecutionContext: ", context);
trace.Trace("Post Context:");
#region try
try
{
trace.Trace("About to get apptEntity");
EntityReference apptEntity = new EntityReference();
trace.Trace("About to set apptEntity");
apptEntity = Appointment.Get(executionContext);
trace.Trace("Set apptEntity");
Entity newAppt = new Entity("appointment");
Entity oldAppt = getAppointment(apptEntity.Id, service);
trace.Trace("apptEntity ID: ",apptEntity.Id);
trace.Trace("newAppt ID: ",newAppt.Id);
trace.Trace("oldAppt ID: ",oldAppt.Id);
foreach (KeyValuePair<string,object> a in oldAppt.Attributes)
{
//continue;
if (a.Key != "activityid")
{
setValueSafely(newAppt.Attributes, a.Key, a.Value);
}
}
foreach (KeyValuePair<string, object> a in newAppt.Attributes)
{
//setValueSafely(newAppt.Attributes, a.Key, a.Value);
trace.Trace("XYZ-Key: ", a.Key);
trace.Trace("XYZ-Value: ", a.Value);
}
trace.Trace("about to call for new apptID");
Guid apptID = new Guid();
try
{
apptID = service.Create(newAppt);
trace.Trace("Grabbed apptID : ", apptID);
}
catch (Exception ex)
{
trace.Trace("Unable to create apptID: ", ex);
trace.HandleException(ex);
return;
}
List<Entity> results = GetRelatedEntities(service, "appointment", apptEntity.Id, "Appointment_Annotation", "annotation").ToList();
trace.Trace("Created results: ", results.Count);
foreach (Entity e in results)
{
Entity note = new Entity("annotation");
trace.Trace("Entity Type: ", e.GetType());
trace.Trace("Logical Name: ",e.LogicalName );
trace.Trace("ID: ",e.Id );
trace.Trace("Starting loop");
trace.Trace(" ");
foreach (var a in e.Attributes.ToList())
{
if (a.Key == "annotationid")
{
continue;
}
trace.Trace(" Value: ", a.Key);
trace.Trace(" Contains: ", a.Value);
trace.Trace(" ToStr: ", a.ToString());
setValueSafely(note.Attributes, a.Key, a.Value);
}
Guid noteID = service.Create(note);
if (noteID == null)
{
trace.Trace("Service.create(note) failed.");
continue;
}
//We need to create the relationship between our new Entity and our new notes.
//relationship.PrimaryEntityRole = EntityRole.Referenced; //important if the relationship is self-referencing
#region relationship
trace.Trace("NOTEID1: ", note.Id);
trace.Trace("NOTEID2: ", noteID);
relatedEntities.Add(new EntityReference(note.LogicalName, noteID));
// Create an object that defines the relationship between the contact and account.
#endregion
trace.Trace("Ending loop");
}
try
{
service.Associate(newAppt.LogicalName, apptID, relationship, relatedEntities);
}
catch (Exception ex)
{
trace.Trace("Crash: ", ex);
}
trace.Trace("DOne tracing.");
trace.HandleSuccess();
}
catch (Exception ex)
{
trace.HandleException(ex);
}
#endregion
}
}
}
[2014-07-23-1933_8037]:7 - Plugin Started!
[2014-07-23-1933_8037]:7 - Message Name: : Update
[2014-07-23-1933_8037]:7 - Primary Entity Name: : appointment
[2014-07-23-1933_8037]:7 - Primary Entity Id: : f6dc676a-8312-e411-93f2-00155d543a19
[2014-07-23-1933_8037]:7 - PluginExecutionContext: : Microsoft.Crm.Workflow.SynchronousRuntime.SynchronousWorkflowContext
[2014-07-23-1933_8037]:7 - Post Context:
[2014-07-23-1933_8037]:7 - About to get apptEntity
[2014-07-23-1933_8037]:7 - About to set apptEntity
[2014-07-23-1933_8037]:7 - Set apptEntity
[2014-07-23-1933_8087]:12 - apptEntity ID: : f6dc676a-8312-e411-93f2-00155d543a19
[2014-07-23-1933_8087]:12 - newAppt ID: : 00000000-0000-0000-0000-000000000000
[2014-07-23-1933_8087]:12 - oldAppt ID: : f6dc676a-8312-e411-93f2-00155d543a19
[2014-07-23-1933_8087]:12 - XYZ-Key: : scheduledend
[2014-07-23-1933_8087]:12 - XYZ-Value: : 7/23/2014 5:00:00 PM
[2014-07-23-1933_8087]:12 - XYZ-Key: : activitytypecode
[2014-07-23-1933_8087]:12 - XYZ-Value: : appointment
[2014-07-23-1933_8087]:12 - XYZ-Key: : subject
[2014-07-23-1933_8087]:12 - XYZ-Value: : Subject 3
[2014-07-23-1933_8087]:12 - XYZ-Key: : scheduledstart
[2014-07-23-1933_8087]:12 - XYZ-Value: : 7/23/2014 4:30:00 PM
[2014-07-23-1933_8087]:12 - XYZ-Key: : organizer
[2014-07-23-1933_8087]:12 - XYZ-Value: : Microsoft.Xrm.Sdk.EntityCollection
[2014-07-23-1933_8087]:12 - XYZ-Key: : requiredattendees
[2014-07-23-1933_8087]:12 - XYZ-Value: : Microsoft.Xrm.Sdk.EntityCollection
[2014-07-23-1933_8087]:12 - XYZ-Key: : optionalattendees
[2014-07-23-1933_8087]:12 - XYZ-Value: : Microsoft.Xrm.Sdk.EntityCollection
[2014-07-23-1933_8087]:12 - about to call for new apptID
[2014-07-23-1933_8387]:42 - Unable to create apptID: : System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]: Cannot insert duplicate key. (Fault Detail is equal to Microsoft.Xrm.Sdk.OrganizationServiceFault).
[2014-07-23-1933_8387]:42 - Cannot insert duplicate key. at Microsoft.Crm.Extensibility.OrganizationSdkServiceInternal.Create(Entity entity, CorrelationToken correlationToken, CallerOriginToken callerOriginToken, WebServiceType serviceType)
at Microsoft.Crm.Extensibility.InprocessServiceProxy.CreateCore(Entity entity)
at NoteCopier.NoteCopier.Execute(CodeActivityContext executionContext)
42 - Complete.