Rafy 框架 - 大批量导入实体

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介:

某些场景下,开发者希望能够大批量地把实体的数据导入到数据库中。虽然使用实体仓库保存实体列表非常方便,但是其内部实现机制是一条一条的保存到数据库,当实体的个数较多时,效率就会很低。所以 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 用户手册》中。

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
8月前
|
API 开发工具 数据库
OneCode2.0源码结构分析
OneCode12月10日正式更新了其V2.0版本。从OneCode的季度版本生命中,可以看到2.0版本还是一个重量级的版本,笔者在收到2.0更新后第一时间下拉了最新的代码。在参考了OneCode 的技术说明后,根据包结构来分析一下OneCode2.0的结构。
|
5月前
|
存储 开发框架 前端开发
EAV模型(实体-属性-值)的设计和低代码的处理方案(2)--数据的查询处理
EAV模型(实体-属性-值)的设计和低代码的处理方案(2)--数据的查询处理
|
5月前
|
存储 开发框架 前端开发
EAV模型(实体-属性-值)的设计和低代码的处理方案(3)-- 实体属性定义及前端列表展示和数据录入处理
EAV模型(实体-属性-值)的设计和低代码的处理方案(3)-- 实体属性定义及前端列表展示和数据录入处理
|
8月前
|
数据采集 自然语言处理 Python
在 Django 中设计爬虫系统的数据模型与多对多关系
在构建爬虫系统时,设计合理的数据模型和多对多关系对系统的性能和可维护性至关重要。本文将探讨如何使用 Django 来设计爬虫系统的数据模型。
16activiti - 流程管理定义(查看流程图附件)
16activiti - 流程管理定义(查看流程图附件)
52 0
|
存储 数据建模
「业务架构」BPMN简介第四部分-数据和工件
「业务架构」BPMN简介第四部分-数据和工件
|
SQL 存储 数据库
其实添加数据也可以这样简单——表单的第一步抽象(针对数据访问层)《怪怪设计论: 抽象无处不在 》有感
更正:不好意思,昨天晚上思路有点混乱。有几个前提忘记说明了,现在补充一下。 1、缩小范围。按照由简到难的思路,这里先讨论最简单的添加数据的情况。就是单表的添加和修改;这里讨论的是webform的情况。
1101 0
|
数据库
10、【分类模块管理】——添加分类接口开发
分类模块:分类模块是给后台管理员进行操作的,所以我们所有的行为都应该是建立在登录者是管理员的前提下。controller: @RequestMapping("add_category.
853 0

热门文章

最新文章

下一篇
开通oss服务