Я пишу плагин для Dynamics 2017 на предпосылке, используя C #. Плагин должен запускать синхронно после операции на выигрыш возможности. Когда я отмечаю возможность как выигранную, я получаю следующую ошибку:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault>
<faultcode>s:Client</faultcode>
<faultstring xml:lang="en-US">VerifyCommitted - Transaction has not been committed</faultstring>
<detail>
<OrganizationServiceFault xmlns="http://schemas.microsoft.com/xrm/2011/Contracts"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<ActivityId>11be55c4-321a-4b84-b9b7-f2451579bc67</ActivityId>
<ErrorCode>-2147220910</ErrorCode>
<ErrorDetails xmlns:a="http://schemas.datacontract.org/2004/07/System.Collections.Generic"/>
<Message>VerifyCommitted - Transaction has not been committed</Message>
<Timestamp>2018-07-05T18:37:53.9996395Z</Timestamp>
<ExceptionRetriable>false</ExceptionRetriable>
<ExceptionSource i:nil="true"/>
<InnerFault i:nil="true"/>
<OriginalException i:nil="true"/>
<TraceText i:nil="true"/>
</OrganizationServiceFault>
</detail>
</s:Fault>
</s:Body>
</s:Envelope>
Я попытался профилировать плагин, чтобы я мог отлаживать то, что здесь происходит, но не похоже, что плагин успешно профилирует действие. Почему я получаю эту ошибку и почему мой плагин неправильно профилирует?
private void ExecutePostOpportunityWin(LocalPluginContext localContext)
{
if (localContext == null)
{
throw new ArgumentNullException("localContext");
}
try
{
IPluginExecutionContext context = localContext.PluginExecutionContext;
Entity wonOpportunityEntity = context.InputParameters.Contains("OpportunityClose") ?
(Entity)context.InputParameters["OpportunityClose"] :
throw new InvalidPluginExecutionException("Unable to load OpportunityClose Input Parameter. Please try again in a few minutes. If the problem persists please contact IT Support.");
EntityReference wonOpportunityReference = wonOpportunityEntity.Attributes.Contains("opportunityid") ?
(EntityReference)wonOpportunityEntity.Attributes["opportunityid"] :
throw new InvalidPluginExecutionException("Unable to load opportunityid. Please try again in a few minutes. If the problem persists please contact IT Support.");
IOrganizationService service = localContext.OrganizationService;
if (wonOpportunityReference != null)
{
Opportunity wonOpportunity = (Opportunity)service.Retrieve(
"opportunity",
new Guid(wonOpportunityReference.Id.ToString()),
new ColumnSet(new String[] {
"customerid",
"ownerid",
"ccseq_salesleadid",
"description",
"ccseq_newcontract",
"ccseq_newclient",
"ccseq_clientid",
"ccseq_contractid",
"name"
})
);
if (wonOpportunity != null)
{
Boolean isNewClient = wonOpportunity.NewClient == true;
Boolean isNewContract = wonOpportunity.NewContract == true;
if (isNewClient && isNewContract)
{
Client newClient = CreateClient(wonOpportunity, service);
Contract newContract = CreateContract(wonOpportunity, newClient, service);
AssociateOpportunityToContract(wonOpportunity.Id, newContract.Id, service);
wonOpportunity.Client = newClient;
wonOpportunity.Contract = newContract;
wonOpportunity.Save(service);
}
else if (isNewClient && !isNewContract)
{
Client newClient = CreateClient(wonOpportunity, service);
AssociateOpportunityToContract(wonOpportunity.Id, wonOpportunity.Contract.Id, service);
wonOpportunity.Client = newClient;
wonOpportunity.Save(service);
}
else if (!isNewClient && isNewContract)
{
Entity entity = service.Retrieve(
"ccseq_client",
wonOpportunity.Client.Id,
new ColumnSet(new String[] { "ccseq_clientid", "ccseq_masterclientid" })
);
Client newClient = (Client)entity;
if (newClient.MasterClient != null)
{
entity = service.Retrieve(
"ccseq_client",
newClient.Id,
new ColumnSet(new String[] { "ccseq_clientid", "ccseq_masterclientid" })
);
newClient = (Client)entity;
}
Contract newContract = CreateContract(wonOpportunity, newClient, service);
AssociateOpportunityToContract(wonOpportunity.Id, newContract.Id, service);
wonOpportunity.Contract = newContract;
wonOpportunity.Save(service);
}
else if (!isNewClient && !isNewContract)
{
AssociateOpportunityToContract(wonOpportunity.Id, wonOpportunity.Contract.Id, service);
}
else
{
throw new InvalidPluginExecutionException("Unable to process Client and Contract Information. Please try again in a few minutes. If the problem persists please contact IT Support.");
}
}
else
{
throw new InvalidPluginExecutionException("Unable to load Opportunity. Please try again in a few minutes. If the problem persists please contact IT Support.");
}
}
else
{
throw new InvalidPluginExecutionException("Unable to load Opportunity. Please try again in a few minutes. If the problem persists please contact IT Support.");
}
}
catch (Exception e)
{
throw new InvalidPluginExecutionException(e.Message);
}
}
private void AssociateOpportunityToContract(Guid opportunityID, Guid contractID, IOrganizationService service)
{
service.Associate(
"ccseq_contract",
contractID,
new Relationship("ccseq_ccseq_contract_opportunity_ContractID"),
new EntityReferenceCollection(
new EntityReference[] { new EntityReference("opportunity", opportunityID) }
)
);
}
private Contract CreateContract(Opportunity opportunity, Client clientGroup, IOrganizationService service)
{
Contract newContract = new Contract();
newContract.ApprovingPartner = opportunity.SalesLead;
newContract.Preparer = opportunity.SalesLead;
newContract.Description = opportunity.Topic;
newContract.Executed = false;
newContract.ContractStatus = Contract.eContractStatus.Draft;
newContract.ClientGroup = clientGroup;
newContract.Id = newContract.Save(service);
ContractLine newContractLine = new ContractLine();
newContractLine.Contract = newContract;
newContractLine.Id = newContractLine.Save(service);
ContractRevenue newContractRevenue = new ContractRevenue();
newContractRevenue.Contract = newContract;
newContractRevenue.Id = newContractRevenue.Save(service);
ContractRevenueByContractLine newContractRevenueByContractLine = new ContractRevenueByContractLine();
newContractRevenueByContractLine.ContractLine = newContractLine;
newContractRevenueByContractLine.ContractRevenue = newContractRevenue;
newContractRevenueByContractLine.Id = newContractRevenueByContractLine.Save(service);
ContractJob newContractJob = new ContractJob();
newContractJob.ContractLine = newContractLine;
newContractJob.Id = newContractJob.Save(service);
return newContract;
}
private Client CreateClient(Opportunity opportunity, IOrganizationService service)
{
Client newClient = new Client();
newClient.Name = opportunity.AssociationOrContact.Name;
newClient.Originator = opportunity.Originator;
newClient.Preparer = opportunity.SalesLead;
newClient.ClientPartner = opportunity.SalesLead;
newClient.ClientStatus = Client.eClientStatus.Draft;
if (opportunity.AssociationOrContact != null)
{
if (opportunity.AssociationOrContact.LogicalName == "account")
{
Association association = null;
association = (Association)service.Retrieve(
"account",
opportunity.AssociationOrContact.Id,
new ColumnSet(new String[]
{
"ownershipcode",
"industrycode",
"ccseq_fiscalyearendmonth",
"ccseq_naicscode",
"address1_line1",
"address1_line2",
"address1_line3",
"address1_city",
"address1_stateorprovince",
"address1_postalcode",
"address1_country"
})
);
if (association != null)
{
newClient.Association = association;
newClient.FiscalYearEndMonth = association.FiscalYearEndMonth != null ? (Client.eMonthOfYear)association.FiscalYearEndMonth : (Client.eMonthOfYear?)null;
//client.ClientType = (Client.eClientType)association.EntityType; // These two option sets are different
newClient.SameAsClientAddress = true;
newClient.Address1 = association.Address1_Street1;
newClient.Address2 = association.Address1_Street2;
newClient.Address3 = association.Address1_Street3;
newClient.City = association.Address1_City;
newClient.State = association.Address1_State_Province;
newClient.Zip = association.Address1_ZIP_PostalCode != null ? Convert.ToInt32(association.Address1_ZIP_PostalCode) : (int?)null;
newClient.Country = association.Address1_County;
newClient.BillingAddress1 = association.Address1_Street1;
newClient.BillingAddress2 = association.Address1_Street2;
newClient.BillingAddress3 = association.Address1_Street3;
newClient.BillingCity = association.Address1_City;
newClient.BillingState = association.Address1_State_Province;
newClient.BillingZip = association.Address1_ZIP_PostalCode != null ? Convert.ToInt32(association.Address1_ZIP_PostalCode) : (int?)null;
newClient.BillingCountry = association.Address1_County;
}
}
else
{
Contact contact = (Contact)service.Retrieve(
"contact",
opportunity.AssociationOrContact.Id,
new ColumnSet(new String[]
{
"firstname",
"lastname",
"emailaddress1"
})
);
if (contact != null)
{
newClient.Name = contact.LastName + " Household";
newClient.BillingContactName = contact.FirstName + " " + contact.LastName;
newClient.BillingContactEmail = contact.PrimaryEmail;
// Address Information doesn't quite line up
}
}
}
newClient.Id = newClient.Save(service);
return newClient;
}
Конфигурация плагина