利用ExecuteMultipleRequest来批量导入数据,成功的成功失败的失败,并生成导入结果文件
我是微软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 ,本博文参考了Magnetism 的Dynamics 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来批量导入数据,成功的成功失败的失败,并生成导入结果文件的更多相关文章
- 利用DataTable快速批量导数据
DataSet ds = new DataSet(); using (SqlConnection conn = new SqlConnection(@"data sou ...
- 使用kettle来根据时间戳或者批次号来批量导入数据,达到增量的效果。
1.Kettle是一款国外开源的ETL工具,纯java编写,可以在Window.Linux.Unix上运行,数据抽取高效稳定.下载图形化界面的zip包格式的,直接解压缩使用即可.安装部署模式这里不说了 ...
- 随笔编号-09 批量导入数据(Mysql)报MySQL server has gone away 问题的解决方法
问题场景: 使用*.sql 脚本,批量导入数据到mysql实例中,使用DOS 界面导入的,期间,到最后一步 source D:\aaa.sql 回车后,系统提示 MySQL server has g ...
- Excel表格导入数据
步骤: 1,选择要插入的数据库--右键--任务--导入数据 2,点击下一步,选择数据源,excel文件路径,和版本信息(注:使用2010及以上版本的office,请先将格式转换为03 或07格式的以便 ...
- ThinkPHP+uploadify+upload+PHPExcel 无刷新导入数据
前端HTML+JQuery 备注Jquery需要1.x版本,不能用2.x版本 1.引入必要文件及上传input <load file="__PUBLIC__/js/jquery-1. ...
- 用代码从文件中导入数据到SQL Server
引言 导入数据到SQL Server 是常见的需求,特别是定期导入这种需求. 对于定期导入主要有以下几种方式可选择: Bulk Insert Bcp Utility OpenRowSet 写程序导入( ...
- geotrellis使用(二十一)自动导入数据
目录 前言 整体介绍 前台界面 后台控制 总结 一.前言 之前Geotrellis数据导入集群采用的是命令行的方式,即通过命令行提交spark任务来ingest数据,待数据导入完毕再启动 ...
- 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 ...
- SQL Server 2008 导出数据与导入数据任务介绍
一. 实例数据库介绍 源数据库Test_Other_DB:存在tb_Class,tb_Student,tb_TestTable三张表. 目标数据库TestDB_Output:空库,不含任何表. 二. ...
随机推荐
- centos 7 MysSQL 5.7.23 二进制安装
MySQL 5.7.23 二进制安装 CentOS 7 将默认数据库MySQL替换成了Mariadb. 这里会从系统的环境准备开始一步一步安装. 环境准备 系统版本 内核版本 IP地址 Centos ...
- 一个缓存使用案例:Spring Cache VS Caffeine 原生 API
最近在学习本地缓存发现,在 Spring 技术栈的开发中,既可以使用 Spring Cache 的注解形式操作缓存,也可用各种缓存方案的原生 API.那么是否 Spring 官方提供的就是最合适的方案 ...
- tp5判断多模块下访问PC端和手机端
现在很多网站的手机端和PC端都是分开的模块,这是问题就来了,有些手机端的用户输入了PC端的网址,直接访问了PC端.下面我教大家如何实现手机端用户访问PC时,跳转回手机端. 解决方法:把下面的代码放到公 ...
- Android组合Windows环境下Frida的安装步骤
Frida是什么 我觉得官网已经说得很清楚了.简单的说就是一款动态代码检测工具,可用于各种系统,这里的主要用途是动态检测Android代码,配合Windows系统环境使用. Frida ...
- 如何使用pandas分析金融数据
[摘要]pandas是数据分析师分析数据最常用的三方库之一,结合matplotlib,非常强大. 首先我们收集一些数据. 从东方财富客户端导出券商信托板块2018年11月1日的基础行情和财务数据.分别 ...
- RS485与RS232
以下内容为结合视频,加上自述对其理解. 信息在传输线上通过电压信息进行传输,一个字节的数据有8位. 当传输一个字节的信息时,通信方式有串行通信与并行通信,在这两种通信方式之中,RS485是并行通信,R ...
- postman tests常用方法
postman常用方法集合: 1.设置环境变量 postman.setEnvironmentVariable("key", "value"); pm.envir ...
- JSSDK制作思路
需求:对外提供一个js的SDK.相当于在原有的原生SDK基础上包装一层方法. SDK原生的方法通过JSExport 协议可以让js调用到原生的方法.你可以写一个协议继承JSExport ,将需要对js ...
- react-native IOS TextInput长按提示显示为中文(select | selectall -> 选择 | 全选)
根据手机系统语言(简体中文/英文),提示不同的长按效果 长按提示效果图 英文长按提示 中文长按提示 解决 1.手机系统语言为简体中文: 设置->通用->语言与地区 2.ios/项目/inf ...
- git 使用详解(10)-- 远程分支
远程分支 远程分支(remote branch)是对远程仓库中的分支的索引.它们是一些无法移动的本地分支:只有在Git 进行网络交互时才会更新.远程分支就像是书签,提醒着你上次连接远程仓库时上面各分支 ...