I have created a small command line application that reads from a spreadsheet and pushes the data into our Dynamics CRM online setup. The actual import is the same as the data management -> data import (using ImportWithCreate.cs) in the Dynamics SDK samples, but I've modified the column mappings to suit our needs.
When I run the command line it reports that its succeeded (it parses, transforms and finally runs the import - as per the sample). Checking in CRM I can see that the data import has been created and run but its displayed as failed (annoyingly it has no message or reason for the failure that I can see).
It displays in CRM like this...
Looking at that graphic I can deduce that the import file has been used (I have a test file with 10 rows and the import reports 10 records in total). Confusingly it says none of the records were Successful, Partially successful or Failures?!
If I attempt to import the same test data file using the same map manually then it works.
Has anyone any pointers on how I can debug this and find out why this isn't working via code?
As requested here's some code snippets. The import is essentially the data management sample out of the Dynamics SDK with the following modifications.
I replaced the samples mapping's examples with the following
// Mapping - Quote Name (text).
ColumnMapping colMappingQuoteName = new ColumnMapping()
{
SourceAttributeName = "Name",
SourceEntityName = "PTBQuote",
TargetAttributeName = "name",
TargetEntityName = Quote.EntityLogicalName,
ImportMapId = new EntityReference(ImportMap.EntityLogicalName, importMapId),
ProcessCode = new OptionSetValue((int)ColumnMappingProcessCode.Process)
};
Guid colMappingIdQuoteName = _serviceProxy.Create(colMappingQuoteName);
// Mapping - Potential Customer (lookup).
ColumnMapping colMappingPotentialCustomer = new ColumnMapping()
{
SourceAttributeName = "PotentialCustomer",
SourceEntityName = "PTBQuote",
TargetAttributeName = "customerid",
TargetEntityName = Quote.EntityLogicalName,
ImportMapId = new EntityReference(ImportMap.EntityLogicalName, importMapId),
ProcessCode = new OptionSetValue((int)ColumnMappingProcessCode.Process)
};
Guid colMappingIdPotentialCustomer = _serviceProxy.Create(colMappingPotentialCustomer);
LookUpMapping parentLookupMappingPotentialCustomer = new LookUpMapping()
{
ColumnMappingId = new EntityReference(ColumnMapping.EntityLogicalName, colMappingIdPotentialCustomer),
ProcessCode = new OptionSetValue((int)LookUpMappingProcessCode.Process),
LookUpEntityName = Account.EntityLogicalName,
LookUpAttributeName = "name",
LookUpSourceCode = new OptionSetValue((int)LookUpMappingLookUpSourceCode.System)
};
Guid parentLookupMappingId = _serviceProxy.Create(parentLookupMappingPotentialCustomer);
// Mapping - PriceList (lookup).
ColumnMapping colMappingPriceList = new ColumnMapping()
{
SourceAttributeName = "PriceList",
SourceEntityName = "PTBQuote",
TargetAttributeName = "pricelevelid",
TargetEntityName = Quote.EntityLogicalName,
ImportMapId = new EntityReference(ImportMap.EntityLogicalName, importMapId),
ProcessCode = new OptionSetValue((int)ColumnMappingProcessCode.Process)
};
Guid colMappingIdPriceList = _serviceProxy.Create(colMappingPriceList);
LookUpMapping parentLookupMappingPriceList = new LookUpMapping()
{
ColumnMappingId = new EntityReference(ColumnMapping.EntityLogicalName, colMappingIdPriceList),
ProcessCode = new OptionSetValue((int)LookUpMappingProcessCode.Process),
LookUpEntityName = PriceLevel.EntityLogicalName,
LookUpAttributeName = "name",
LookUpSourceCode = new OptionSetValue((int)LookUpMappingLookUpSourceCode.System)
};
Guid parentLookupMappingIdPriceList = _serviceProxy.Create(parentLookupMappingPriceList);
// Mapping - Currency (lookup).
ColumnMapping colMappingCurrency = new ColumnMapping()
{
SourceAttributeName = "Currency",
SourceEntityName = "PTBQuote",
TargetAttributeName = "transactioncurrencyid",
TargetEntityName = Quote.EntityLogicalName,
ImportMapId = new EntityReference(ImportMap.EntityLogicalName, importMapId),
ProcessCode = new OptionSetValue((int)ColumnMappingProcessCode.Process)
};
Guid colMappingIdCurrency = _serviceProxy.Create(colMappingCurrency);
LookUpMapping parentLookupMappingCurrency = new LookUpMapping()
{
ColumnMappingId = new EntityReference(ColumnMapping.EntityLogicalName, colMappingIdCurrency),
ProcessCode = new OptionSetValue((int)LookUpMappingProcessCode.Process),
LookUpEntityName = TransactionCurrency.EntityLogicalName,
LookUpAttributeName = "currencyname",
LookUpSourceCode = new OptionSetValue((int)LookUpMappingLookUpSourceCode.System)
};
Guid parentLookupMappingIdCurrency = _serviceProxy.Create(parentLookupMappingCurrency);
// Mapping - Effective From (text).
ColumnMapping colMappingEffectiveFrom = new ColumnMapping()
{
SourceAttributeName = "EffectiveFrom",
SourceEntityName = "PTBQuote",
TargetAttributeName = "effectivefrom",
TargetEntityName = Quote.EntityLogicalName,
ImportMapId = new EntityReference(ImportMap.EntityLogicalName, importMapId),
ProcessCode = new OptionSetValue((int)ColumnMappingProcessCode.Process)
};
Guid colMappingIdEffectiveFrom = _serviceProxy.Create(colMappingEffectiveFrom);
// Mapping - Effective To (text).
ColumnMapping colMappingEffectiveTo = new ColumnMapping()
{
SourceAttributeName = "EffectiveTo",
SourceEntityName = "PTBQuote",
TargetAttributeName = "effectiveto",
TargetEntityName = Quote.EntityLogicalName,
ImportMapId = new EntityReference(ImportMap.EntityLogicalName, importMapId),
ProcessCode = new OptionSetValue((int)ColumnMappingProcessCode.Process)
};
Guid colMappingIdEffectiveTo = _serviceProxy.Create(colMappingEffectiveTo);
// Mapping - Owner (lookup).
ColumnMapping colMappingOwner = new ColumnMapping()
{
SourceAttributeName = "Owner",
SourceEntityName = "PTBQuote",
TargetAttributeName = "ownerid",
TargetEntityName = Quote.EntityLogicalName,
ImportMapId = new EntityReference(ImportMap.EntityLogicalName, importMapId),
ProcessCode = new OptionSetValue((int)ColumnMappingProcessCode.Process)
};
Guid colMappingIdOwner = _serviceProxy.Create(colMappingOwner);
LookUpMapping parentLookupMappingOwner = new LookUpMapping()
{
ColumnMappingId = new EntityReference(ColumnMapping.EntityLogicalName, colMappingIdOwner),
ProcessCode = new OptionSetValue((int)LookUpMappingProcessCode.Process),
LookUpEntityName = SystemUser.EntityLogicalName,
LookUpAttributeName = "fullname",
LookUpSourceCode = new OptionSetValue((int)LookUpMappingLookUpSourceCode.System)
};
Guid parentLookupMappingIdOwner = _serviceProxy.Create(parentLookupMappingOwner);
// Mapping - Status (picklist).
ColumnMapping colMappingStatus = new ColumnMapping()
{
SourceAttributeName = "Status",
SourceEntityName = "PTBQuote",
TargetAttributeName = "statecode",
TargetEntityName = Quote.EntityLogicalName,
ImportMapId = new EntityReference(ImportMap.EntityLogicalName, importMapId),
ProcessCode = new OptionSetValue((int)ColumnMappingProcessCode.Process)
};
Guid colMappingIdStatus = _serviceProxy.Create(colMappingStatus);
// Picklist values - any changes will need to be confirmed against Dynamics CRM (TargetValue being the tricky bit to get right)
PickListMapping pickListMappingStatus0 = new PickListMapping()
{
SourceValue = "Draft",
TargetValue = 0,
ColumnMappingId = new EntityReference(ColumnMapping.EntityLogicalName, colMappingIdStatus),
ProcessCode = new OptionSetValue((int)PickListMappingProcessCode.Process)
};
Guid picklistMappingIdStatus0 = _serviceProxy.Create(pickListMappingStatus0);
then I updated the Import file creation to the following (path is just a var holding the full path to the csv file that I'm importing)
importFile = new ImportFile()
{
Content = BulkImportHelper.ReadCsvFile(path),
Name = "Automated quote import",
IsFirstRowHeader = true,
ImportMapId = new EntityReference(ImportMap.EntityLogicalName, importMapId),
UseSystemMap = false,
Source = path,
SourceEntityName = "PTBQuote",
TargetEntityName = Quote.EntityLogicalName,
ImportId = new EntityReference(Import.EntityLogicalName, importId),
EnableDuplicateDetection = false,
FieldDelimiterCode =
new OptionSetValue((int)ImportFileFieldDelimiterCode.Comma),
DataDelimiterCode =
new OptionSetValue((int)ImportFileDataDelimiterCode.DoubleQuote),
ProcessCode =
new OptionSetValue((int)ImportFileProcessCode.Process)
};