I'm attempting to use Microsoft Dynamics CRM SDK to update a record programmatically. Unfortunatey, after I pull the record, update the fields, and call the .Update()
method on my service proxy I get the following exception:
[System.ServiceModel.FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>]
System.InvalidCastException: Microsoft Dynamics CRM has experienced an error.
Reference number for administrators or support: #B08B34D9"
System.ServiceModel.FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>
Since I've never used CRM before, and we have scare resources that currently use it within the company, I don't know how/where to begin investigating the exception, or any idea where it could come from.
The program begins with the following method. This simply queries the data for a matching EIN number. If no records are found then I use a .Create()
method. If records are found we update the currently existing item in Dynamics.
public string UpdateDynamics(AgentTransmission agt)
{
ConditionExpression condition = new ConditionExpression();
condition.AttributeName = "neu_taxid";
condition.Operator = ConditionOperator.Equal;
condition.Values.Add("012-3456787");
ColumnSet columns = new ColumnSet(true);
QueryExpression query = new QueryExpression();
query.ColumnSet = columns;
query.EntityName = "account";
query.Criteria.AddCondition(condition);
OrganizationServiceClient client = new OrganizationServiceClient();
EntityCollection collection = client.RetrieveMultiple(query);
if (collection.Entities.Count == 0)
{
_servicePoxy.Create(CreateAccount(agt));
}
else
{
foreach (Entity contact in collection.Entities)
{
//This throws the exception
_servicePoxy.Update(CreateAccount(agt, contact.Id));
}
}
return string.Empty;
}
Below is the method I use to create the Entity
object we pass to Dynamics. The data is pulled from an Entity Framework model object and mapped to the appropriate field.
private Entity CreateAccount(AgentTransmission agt, Guid Id = new Guid())
{
_account = new Entity();
_account.LogicalName = "account";
_account.Attributes.Add("name", agt.AgencyName);
_account.Attributes.Add("telephone1", agt.BusinessPhone.Replace("(","").Replace(")", "").Replace("-", ""));
_account.Attributes.Add("address1_line1", agt.MailingStreet1);
_account.Attributes.Add("address1_city", agt.MailingCity);
_account.Attributes.Add("address1_postalcode", agt.MailingZip);
_account.Attributes.Add("neu_address1stateprovince", LookupStateCode(agt.MailingState));
_account.Attributes.Add("address1_addresstypecode", new OptionSetValue(1)); //1 for Mailing
_account.Attributes.Add("neu_channelid", LookupChannelId(agt.Channel));
_account.Attributes.Add("neu_appointmentstatus", new OptionSetValue(279660000));
_account.Attributes.Add("customertypecode", LookupCustomerCode(agt.RelationshipType));
_account.Attributes.Add("neu_taxid", UnobfuscateRef(agt.ReferenceNumber).ToString());
//If we're doing an update will need the GUID. Only use when Update is needed.
if (Id != Guid.Empty)
{
_account.Attributes.Add("accountid", Id);
}
return _account;
}
The .Create()
method works as it's supposed to, however, so I think that the exception is isolated to the accountid
GUID attribute I use for updates.
In your CreateAccount
method when you are processing existing entities, try changing this line:
_account.Attributes.Add("accountid", Id);
to
_account.Id = Id;
Theoretically, it shouldn't matter but the Id
property of the entity instance should always be set for existing records.
You might also want to consider passing in an account entity (which you call contact in your for loop) instead of the id into CreateAccount
as a parameter and then you wouldn't have to explicitly create an account instance in each call and could also remove the logic which tries to assign the id (as the passed in entity would already have it defined).
For example, your calls would be:
_servicePoxy.Create(CreateAccount(agt), new Entity("account"));
and
_servicePoxy.Update(CreateAccount(agt, contact));
And then you could remove these lines from CreateAccount
:
_account = new Entity();
_account.LogicalName = "account";
and
if (Id != Guid.Empty)
{
_account.Attributes.Add("accountid", Id);
}
(I would have posted this as more of a comment, but I don't have enough permissions.)