某些场景下,开发者希望能够大批量地把实体的数据导入到数据库中。虽然使用实体仓库保存实体列表非常方便,但是其内部实现机制是一条一条的保存到数据库,当实体的个数较多时,效率就会很低。所以 Rafy 设计了批量导入插件程序,其内部使用 ADO.NET 及 ODP.NET 中的批量导入机制来把大量数据一次性导入到数据库中。

使用方法


步骤
  1. 由于批量导入功能是一个额外的程序集,所以在使用该功能时,需要先使用 NuGet 引用最新版本的 Rafy.Domain.ORM.BatchSubmit 程序集。

  2. 如果准备导入 ORACLE 数据库,则也需要引用 Oracle.ManagedDataAccess(12.1.022 以上版本) 程序集。

  3. 修改需要保存大量实体的代码,例如,原代码如下:

var books = new BookList();
for (int i = 0; i < 1000000; i++)
{
var book = new Book
{
ChapterList =
{
new Chapter(),
new Chapter(),
}
};
books.Add(book);
} //直接使用实体仓库进行保存。
repo.Save(books);

需要把最后一行使用仓库保存实体列表,修改为创建导入器来保存实体列表:

//创建一个批量导入器进行保存。
repo.CreateImporter().Save(books);

注意


  • 从上面的代码可以看出,批量导入程序是面向整个聚合的。也就是说,批量导入父实体时,同时也会批量导入父实体下的所有子实体。

  • 批量导入不但支持添加新实体,同时也支持批量更新、批量删除。使用方法与使用仓库保持一致。

  • 对于大批量的数据,使用批量导入,比直接使用仓库来保存实体,速度要快两个数据级左右。

  • 目前批量导入实体的功能,只支持 Oracle 和 SqlServer 两个数据库。

  • 在使用 Oracle 数据库时,还需要在数据库生成完成后,特别地调用以下代码以启用某个聚合实体的批量导入功能,否则导入过程中会抛出异常(原因请见后面的实现原理章节)。代码如下:

Rafy.Domain.ORM.BatchSubmit.Oracle.OracleBatchImporter.EnableBatchSequence(
RF.Concrete<OriginalDataRepository>()
);
 

实现原理


下面简要介绍批量导入的原理。

Sql Server

对于 Sql Server 数据库的批量保存:

  • 批量新增数据,是使用 System.Data.SqlClient.SqlBulkCopy 来实现的。

  • 批量更新数据,是使用 System.Data.SqlClient.SqlDataAdapter 来实现的。

  • 批量删除数据,则是直接拼接 SQL 语句,把需要删除的实体的 Id 放到 In 语句中进行删除。例如:

DELETE FROM Books WHERE Id IN (1,3,5,7......);
 
Oracle

对于 Oracle 数据库的批量保存:

  • 新增数据、更新数据都是使用 ODP.NET 中原生的批量导入功能。

    参见:Oracle.ManagedDataAccess.Client.OracleCommand.ArrayBindCount 属性。

  • 而删除数据的实现则和 SQLServer 的实现一致,均是拼接 DELETE 语句。

新增大量实体时,实体的 Id 生成

一般情况下,使用仓库保存一个新增的实体时,仓库会使用数据库本身的机制来为实体生成 Id,在 SQLServer 中是使用 IDENTITY 列,在 ORACLE 中则是使用每个表对应的 SEQUENCE 来生成。但是,批量导入大量新实体时,为了性能上的考虑,则需要一次性为需要保存的所有新实体统一生成 Id。

在 SQLServer 中,可以方便地使用 SQL 语句调整表中 IDENTITY 下一次的值,所以实现比较简单。只需要设置 IDENTITY 下一次的值 + 100000,并使用中间跳过的这些值来作为实体的 Id 即可。

但是在 ORACLE 中,如果去调整 SEQUENCE 的值,则属于 DDL 语句,会隐式自动提交事务,会造成数据的错误。所以我们最终决定:如果在 ORACLE 中要使用批量导入功能,数据表对应的 SEQUENCE 必须以较大的数字为步距(如 ALTER SEQUENCE "SEQ_TABLE_ID" INCREMENT BY 100000 NOCACHE)。这样,在批量导入时,就不再需要增修改 SEQUENCE 的步距,而直接使用中间跳过的这些值作为实体的 Id。这样做也比较方便,但是负面效果则是使用仓库保存单一实体时,两次保存不同实体生成的 Id 会相差 100000,不再是连续的。

PS:该文已经纳入《 Rafy 用户手册》中。

Rafy 框架 - 大批量导入实体的更多相关文章

  1. 福利到!Rafy(原OEA)领域实体框架 2.22.2067 发布!

    距离“上次框架完整发布”已经过去了一年半了,应群中的朋友要求,决定在国庆放假之际,把最新的框架发布出来,并把帮助文档整理出来,这样可以方便大家快速上手.   发布内容 注意,本次发布,只包含 Rafy ...

  2. Rafy 领域实体框架 - 树型实体功能(自关联表)

      在 Rafy 领域实体框架中,对自关联的实体结构做了特殊的处理,下面对这一功能进行讲解. 场景 在开发数据库应用程序时,往往会遇到自关联表的场景.例如,分类信息.组织架构中的部门.文件夹信息等,都 ...

  3. Rafy 框架 - 实体支持只更新部分变更的字段

    Rafy 快一两年没有大的更新了.并不是这个框架没人维护了.相反,主要是因为自己的项目.以及公司在使用的项目,都已经比较稳定了,也没有新的功能添加.但是最近因为外面使用了 Rafy 的几个公司,找到我 ...

  4. Rafy 框架 - 幽灵插件(假删除)

      Rafy 框架又添新成员:幽灵插件.本文将解释该插件的场景.使用方法.原理.   场景 在开发各类数据库应用系统时,往往需要在删除数据时不是真正地删除数据,而只是把数据标识为'已删除'状态.这些数 ...

  5. 使用 NuGet 下载最新的 Rafy 框架及文档

    为了让开发者更方便地使用 Rafy 领域实体框架,本月,我们已经把最新版本的 Rafy 框架程序集发布到了 nuget.org 上,同时,还把 RafySDK 的最新版本发布到了 VisualStud ...

  6. Rafy 框架 - 通用查询条件(CommonQueryCriteria)

    在应用开发过程中,有 80% 的场景下,开发者所需要的实体查询,查询条件中其实都是一些简单的属性匹配,又或是一些属性匹配的简单组合.Rafy 为这样的场景提供了更为方便使用的 API:CommonQu ...

  7. 一位同事对 Rafy 框架的一些建议及我的回复

    下面是一位同事对当前的产品开发框架提出的一些建议,以及我的回复.我觉得一些问题提得有一定的代表性,在征得本人同意后,将本邮件发布在博客中. 同时,也非常希望对框架.产品有好的建议的小伙伴,都可以给我发 ...

  8. Rafy 框架 - 使用 SqlTree 查询

    本文介绍如何使用 Rafy 框架中的 Sql Tree 查询: 除了开发者常用的 Linq 查询,Rafy 框架还提供了 Sql 语法树的方式来进行查询. 这种查询方式下,开发者不需要直接编写真正的 ...

  9. Rafy 框架 - 流水号插件

    Rafy 框架又添新成员:流水号插件.本文将解释 Rafy 框架中的流水插件的场景.使用方法. 场景 在开发各类数据库应用系统时,往往需要生成从一开始的流水号,有时还需要按月或者按日进行独立生成,如下 ...

随机推荐

  1. 《Django By Example》第三章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:第三章滚烫出炉,大家请不要吐槽文中 ...

  2. 基于fis3的组件可视化道路

    首先说明一下,即使不熟悉fis3,阅读文本应该也会有所收获. 本文以fis-parser-imweb-tplv2插件为模板插件,目的不在于使用哪个模板,而是组件可视化的实现思路,不必担心. 先说说模板 ...

  3. 【干货分享】流程DEMO-资产请购单

    流程名: 资产请购  业务描述: 流程发起时,会检查预算,如果预算不够,流程必须经过总裁审批,如果预算够用,将发起流程,同时占用相应金额的预算,但撤销流程会释放相应金额的预算.  流程相关文件: 流程 ...

  4. 设置Hyper-V和VMware多个服务之间共存

    这个方法是解决多个服务之间不能共存,下面相当于是以Hyper-V和VMware做例子,其他的也适用. 今天准备安装VMware Workstation 10,然后玩玩MAC OS. 没想到,淡定的我双 ...

  5. ORACLE中STATUS为INACTIVE但是SERVER为SHARED状态的会话浅析

    我们知道当ORACLE数据库启用共享服务器模式时,通过共享服务器模式连接到数据库的会话是有一些特征的.在v$session里面,其SERVER的状态一般为SHARED和NONE, 为SHARED时,表 ...

  6. 编写简单的Makefile文件

    makefile中的编写内容如下: www:hello.c x.h gcc hello.c -o hello clean: rm hello www:hello.c  x.h 表示生成www这个文件需 ...

  7. samba服务

    安装samba服务步骤ps -e 查看进程ps -e | grep 文件名 管道符的使用rpm -qa 安装包的查看rpm -qa | grep samba 抓Samba安装包 注释:包与包之间有依赖 ...

  8. thinkphp-无限分类下根据任意部门获取顶级部门ID

    根据所得到的部门编号获取顶级部门ID: 参数 - department_id 表格组织架构: tab_departments department_id parent_id name 1 1 顶级 2 ...

  9. Linux环境下shell和vim中乱码原因及消除办法

    shell和vim中乱码原因及消除办法 作者:Jack47 在Linux下开发,经常遇到乱码问题:shell或者vim中显示不了中文,或者能够显示,但不能输入中文.每次都是上网去搜,或者同事告诉我一些 ...

  10. ABP源码分析五:ABP初始化全过程

    ABP在初始化阶段做了哪些操作,前面的四篇文章大致描述了一下. 为个更清楚的描述其脉络,做了张流程图以辅助说明.其中每一步都涉及很多细节,难以在一张图中全部表现出来.每一步的细节(会涉及到较多接口,类 ...