我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面的微软最有价值专家(Microsoft MVP),欢迎关注我的微信公众号 MSFTDynamics365erLuoYong ,回复377或者20191109可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!

我前面的博文 Dynamics 365 Customer Engagement的标准导入不支持并行导入了吗? 提供了多进程使用ExecuteMultipleRequest导入数据的程序,速度虽然挺快的,但是有一个问题,导入失败的并不知道是哪些,没有办法统计,这里我改善一下。

关于ExecuteMultipleRequest,请参考官方文档,Use ExecuteMultiple to improve performance for bulk data load ,官方代码示例请参考 ExecuteMultipleRequest Class ,本博文参考了MagnetismDynamics CRM ExecuteMultipleResponse – Analysing the Results

要做到成功的成功,失败的失败,记得要将 ExecuteMultipleSettings 的 ContinueOnError 设置为 true,要记录失败的原因记得要将 ExecuteMultipleSettings 的 ReturnResponses 设置为 true。

直接上代码:

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Messages;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.ServiceModel;
using System.Threading; namespace BulkImportRecords
{
class Program
{
public static IServiceManagement<IOrganizationService> sm;
public static AuthenticationCredentials authCredentials;
static int importsequencenumberstartat = Convert.ToInt32(ConfigurationManager.AppSettings["importsequencenumberstartat"]);
static int threadcount = Convert.ToInt32(ConfigurationManager.AppSettings["threadcount"]);
static string resultFile = ConfigurationManager.AppSettings["resultFile"];
static void Main(string[] args)
{
sm = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri(ConfigurationManager.AppSettings["orgUrl"]));
authCredentials = new AuthenticationCredentials();
authCredentials.ClientCredentials.UserName.UserName = ConfigurationManager.AppSettings["userName"];
authCredentials.ClientCredentials.UserName.Password = ConfigurationManager.AppSettings["passWord"];
authCredentials = sm.Authenticate(authCredentials);
try
{
for (var i = ; i < threadcount; i++)
{
Thread newThread = new Thread(new ParameterizedThreadStart(Work));
newThread.Start(i);
}
Console.ReadKey();
}
catch (FaultException ex)
{
Console.WriteLine("程序出现异常:ex.Message=" + ex.Message);
Console.ReadKey();
}
} static void Work(object data)
{
ExecuteMultipleResponse multiRep;
List<string> content = new List<string>();
try
{
Console.WriteLine("线程开始" + DateTime.Now.ToLongTimeString() + ";线程ID:" + Thread.CurrentThread.ManagedThreadId + ";接收的参数值为:" + data.ToString());
int importsequencenumber = importsequencenumberstartat + Convert.ToInt32(data);
OrganizationServiceProxy orgSvc = new OrganizationServiceProxy(sm, authCredentials.ClientCredentials);
string strReadFilePath = ConfigurationManager.AppSettings["filename"];
int i = ;
int j = ;
int z = ;
ExecuteMultipleRequest multiReqs = new ExecuteMultipleRequest()
{
Settings = new ExecuteMultipleSettings()
{
ContinueOnError = true,
ReturnResponses = true
},
Requests = new OrganizationRequestCollection()
};
using (StreamReader srReadFile = new StreamReader(string.Format(strReadFilePath, (Convert.ToInt32(data) + ).ToString(""))))
{
while (!srReadFile.EndOfStream)
{
string strReadLine = srReadFile.ReadLine(); //读取每行数据
if (i != )//如果第一行包括标题的话要过滤掉
{
content.Add(strReadLine);
var arrLine = strReadLine.Split(',');
CreateRequest req = new CreateRequest();
var createEntity = new Entity("ly_test");
createEntity["ly_name"] = arrLine[];
createEntity["ly_singletext1"] = arrLine[];
createEntity["ly_singletext2"] = arrLine[];
createEntity["ly_singletext3"] = arrLine[];
createEntity["importsequencenumber"] = Convert.ToInt32(importsequencenumber);
req.Target = createEntity;
if (j <= )
{
multiReqs.Requests.Add(req);
}
else
{
multiReqs.Requests = new OrganizationRequestCollection();
multiReqs.Requests.Add(req);
j = ;
}
if (j == )
{
multiRep = (ExecuteMultipleResponse)orgSvc.Execute(multiReqs);
foreach(var Rep in multiRep.Responses)
{
if(Rep.Fault != null)
{
File.AppendAllText(string.Format(resultFile, (Convert.ToInt32(data) + ).ToString("")), $"{content[z*1000+Rep.RequestIndex+1]},FAIL,{Rep.Fault.Message}" + Environment.NewLine);
}
else
{
File.AppendAllText(string.Format(resultFile, (Convert.ToInt32(data) + ).ToString("")), $"{content[z * 1000 + Rep.RequestIndex+1]},OK,{((CreateResponse)Rep.Response).id}" + Environment.NewLine);
}
}
z++;
Console.WriteLine("线程:" + Thread.CurrentThread.ManagedThreadId + "-导入完毕" + z* + "条" + DateTime.Now.ToString());
}
j++;
}
else
{
content.Add($"{strReadLine},结果,消息");
File.AppendAllText(string.Format(resultFile, (Convert.ToInt32(data) + ).ToString("")), content[] + Environment.NewLine);
}
i++;
}
}
multiRep = (ExecuteMultipleResponse)orgSvc.Execute(multiReqs);
foreach (var Rep in multiRep.Responses)
{
if (Rep.Fault != null)
{
File.AppendAllText(string.Format(resultFile, (Convert.ToInt32(data) + ).ToString("")), $"{content[z * 1000 + Rep.RequestIndex+1]},FAIL,{Rep.Fault.Message}" + Environment.NewLine);
}
else
{
File.AppendAllText(string.Format(resultFile, (Convert.ToInt32(data) + ).ToString("")), $"{content[z * 1000 + Rep.RequestIndex+1]},OK,{((CreateResponse)Rep.Response).id}" + Environment.NewLine);
}
}
Console.WriteLine("线程结束" + DateTime.Now.ToLongTimeString() + ";线程ID:" + Thread.CurrentThread.ManagedThreadId);
}
catch(FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault> ex)
{
Console.WriteLine("执行遇到异常:" + ex.Detail.ErrorCode + ex.Message + ex.StackTrace);
}
catch (Exception e)
{
Console.WriteLine("执行遇到异常:" + e.Message + e.StackTrace);
}
}
}
}

配套的app.config内容如下:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
</startup>
<appSettings>
<add key="userName" value="crmadmin@luoyong.me"/>
<add key="passWord" value="Password"/>
<add key="orgUrl" value="https://demo.luoyong.me/XRMServices/2011/Organization.svc"/>
<add key="filename" value="D:\dataimport\data{0}.csv"/>
<add key="importsequencenumberstartat" value="1000000"/>
<add key="threadcount" value="2"/>
<add key="resultFile" value="D:\ImportResult{0}.csv"/>
</appSettings>
</configuration>

为了看到测试效果,我对要导入的实体新建了一个实时工作流如下,如果测试实体的名称字段包括5或者6就以【已取消】的状态停止工作流,并设置好错误信息。

然后我就执行后看到生成的执行结果CSV文件如下,如果CSV文件用Excel打开中文是乱码,就将CSV文件以 UTF-8 with BOM 编码格式另存为一下就可以了。

可以看到有成功,有失败的,失败的告知的原因也是正确的,插入记录成功的记录了插入记录后该记录的主键ID。

利用ExecuteMultipleRequest来批量导入数据,成功的成功失败的失败,并生成导入结果文件的更多相关文章

  1. 利用DataTable快速批量导数据

    DataSet ds = new DataSet();            using (SqlConnection conn = new SqlConnection(@"data sou ...

  2. 使用kettle来根据时间戳或者批次号来批量导入数据,达到增量的效果。

    1.Kettle是一款国外开源的ETL工具,纯java编写,可以在Window.Linux.Unix上运行,数据抽取高效稳定.下载图形化界面的zip包格式的,直接解压缩使用即可.安装部署模式这里不说了 ...

  3. 随笔编号-09 批量导入数据(Mysql)报MySQL server has gone away 问题的解决方法

    问题场景: 使用*.sql 脚本,批量导入数据到mysql实例中,使用DOS 界面导入的,期间,到最后一步 source D:\aaa.sql  回车后,系统提示 MySQL server has g ...

  4. Excel表格导入数据

    步骤: 1,选择要插入的数据库--右键--任务--导入数据 2,点击下一步,选择数据源,excel文件路径,和版本信息(注:使用2010及以上版本的office,请先将格式转换为03 或07格式的以便 ...

  5. ThinkPHP+uploadify+upload+PHPExcel 无刷新导入数据

    前端HTML+JQuery  备注Jquery需要1.x版本,不能用2.x版本 1.引入必要文件及上传input <load file="__PUBLIC__/js/jquery-1. ...

  6. 用代码从文件中导入数据到SQL Server

    引言 导入数据到SQL Server 是常见的需求,特别是定期导入这种需求. 对于定期导入主要有以下几种方式可选择: Bulk Insert Bcp Utility OpenRowSet 写程序导入( ...

  7. geotrellis使用(二十一)自动导入数据

    目录 前言 整体介绍 前台界面 后台控制 总结 一.前言        之前Geotrellis数据导入集群采用的是命令行的方式,即通过命令行提交spark任务来ingest数据,待数据导入完毕再启动 ...

  8. oracle 导出数据和导入数据

    导出数据 exp zl_gj/zlkj@gqxt  grants=y tables=(zl_gj.ckgj,zl_gj.gjlx,zl_gj.rkgj) file=c:\gj.dmp log=c:\g ...

  9. SQL Server 2008 导出数据与导入数据任务介绍

    一. 实例数据库介绍 源数据库Test_Other_DB:存在tb_Class,tb_Student,tb_TestTable三张表. 目标数据库TestDB_Output:空库,不含任何表. 二. ...

随机推荐

  1. firefox常用插件总结

    当初因为ctf比赛而接触啦firefox,慢慢的在firfox上安装满啦各种插件,今天就想着总结一下,给那些刚玩firefox的朋友一些小小的帮助也是好的. 1:Firebug    Firefox强 ...

  2. 设置属性节点(setAttribute())

    setAttribute():方法将为给定元素节点添加一个新的属性值或是改变它的现有属性值: element.setAttribute(attriibuteName,attributeValue); ...

  3. day20191001国庆默写

    day20191001国庆默写恢复 重在理解,而不是死记硬背.认真专心看6遍,做6遍. 学会码字,每天码字二小时.持之以恒. 任重道远,出发,走多少算多少.100分的试卷,会做20分也比一个努力也没有 ...

  4. 程序员的算法课(3)-递归(recursion)算法

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/m0_37609579/article/de ...

  5. python函数-函数对象

    python函数-函数对象 实验室 当函数定义时,就类似a=1,以函数名为变量名 def zx(): pass print(zx) zx=21 print(zx) <function zx at ...

  6. Kafka分区分配策略分析——重点:StickyAssignor

    “ 为什么Kafka在RangeAssigor.RoundRobinAssignor的基础上,又新增了PartitionAssignor,它解决了什么问题?” 背景 用过Kafka的同学应该都知道Ka ...

  7. layui中formSelects的使用

    1.下载 下载地址:https://github.com/hnzzmsf/layui-formSelects 2. 引入 //引入formSelects.css <link rel=" ...

  8. 简单理解http协议的特性

    http协议一种数据传输的规范,像我们的在发送数据的时候,我们无法保证发送与接收的类型是一致的,它就保证了我们传输的同一个类型数据. 特性: 1.灵活:我们不管传输什么数据,图片,文件,文字,都可以进 ...

  9. luogu P3805 【模板】manacher算法

    题目描述 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 字符串长度为n 输入格式 一行小写英文字符a,b,c...y,z组成的字符串S 输出格式 一个整数表示 ...

  10. react-native布局中的层级问题(zIndex,elevation)

    目录 关于层级的zIndex/elevation 1.zIndex是rn在0.30开始支持的属性,是可以生效的: 2.shadow和elevation 结论 关于层级的zIndex/elevation ...