我创建了一个小型命令行应用程序,它从电子表格中读取数据并将数据推送到我们的 Dynamics CRM 在线设置中。实际导入与 Dynamics SDK 示例中的数据管理 -> 数据导入(使用 ImportWithCreate.cs)相同,但我修改了列映射以满足我们的需求。
当我运行命令行时,它报告成功(它解析、转换并最终运行导入 - 根据示例)。检查 CRM,我可以看到数据导入已创建并运行,但显示为失败(令人烦恼的是,它没有我看到的失败消息或原因)。
它在 CRM 中显示如下...
查看该图形,我可以推断导入文件已被使用(我有一个包含 10 行的测试文件,导入报告总共有 10 条记录)。令人困惑的是,它说没有任何记录是成功、部分成功或失败?!
如果我尝试使用相同的地图手动导入相同的测试数据文件,那么它会起作用。
有人告诉我如何调试它并找出为什么它不能通过代码工作吗?
根据要求,这里有一些代码片段。导入本质上是 Dynamics SDK 中的数据管理示例,并进行了以下修改。
我用以下内容替换了示例映射的示例
// 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);
然后我将导入文件创建更新为以下内容(path只是一个保存我要导入的 csv 文件的完整路径的 var)
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)
};
导航到设置 > 系统作业。通过这种方式,您可以检查各个导入作业的状态和任何错误消息:解析、转换、导入。您可能需要过滤网格或对系统作业类型进行高级查找才能找到您需要的记录。
仔细检查 ImportFile 的 SourceEntityName 属性是否与数据映射中的值匹配。您可以导出数据图并在高级设置 > 数据管理 > 数据图 > 导出中查看 XML。就我而言,当他们不同时,我的导入将失败,而不会像问题中那样处理任何行,但当它们匹配时,它就会成功。