前言
EFCore.BulkExtensions是一个常用的EF core 批量处理数据的库.
但是支持的数据库相对较少.特别是.NET5.0版本 连MySQL都无法支持
这个库就是改造的最新EFCore.BulkExtensions的代码
让它能在.NET5.0中支持Mysql和达梦数据库
由于5.0在升到最新9.0的过程中有比较重大的改变,所以.NET8+的 我还在弄..估计后面支持吧
详细说明
使用方法如下:
using (TestDbContext ctx = new TestDbContext())
{
List<Book> books2 = TestBulkInsert1.BuildBooks();
ctx.BulkInsert(books2); //批量插入
var book3 = ctx.Books.Take(1000).ToList();
ctx.BulkDelete(book3); //按实体批量删除
ctx.Books.Where(a => a.BookType == BookType.Fictional).BatchDelete(); //按条件删除
ctx.Books.Where(a => a.BookType == BookType.Scientific).BatchUpdate(a => new Book { Price = a.Price + 50, AuthorName = "gzy666" }); //批量按条件更新
var list = ctx.Books.Take(5000).ToList();
list.ForEach(a => a.AuthorName = "gzy8998");
ctx.BulkUpdate(list); //按实体批量更新
}
比较实用的是批量按实体进行修改、批量按实体删除、批量插入
7.0+虽然支持了按条件进行修改和删除但是批量处理 还是并未支持.
主要讲解一下两个数据库的实现原理吧
1.MySql的实现方式
1.1批量插入
这其实就不用介绍了,就是最常见的SqlBulkCopy的形式进行数据导入
优点就是量大管饱,速度快
缺点就是已经脱离了执行SQL的范畴,所以在实体监听这些处理会比较麻烦
注意:Mysql使用SqlBulkCopy需要开启local_infile功能,并需要在连接字符串中配置:AllowLoadLocalInfile=true;
1.2批量修改
采用了Mysql的 on duplicate key update 语法进行批量处理
首先会创建临时表,然后通过SqlBulkCopy将数据批量导入至临时表中
然后通过 解析实体产生 on duplicate key update 语法
类似如下SQL:
INSERT INTO my_table (column1, column2)
SELECT column1 FROM TempTableName AS EXCLUDED
ON DUPLICATE KEY UPDATE <column1> = <value1>, <column2> = <value2>;
它会通过主键来判断数据是否更新,然后从临时表中将数据更新过去
最后会删除临时表,(mysql也可以配置为会话临时表,这样就不用手动删除,会话结束了 会自动删除)
1.3批量删除
采用了 DELETE INNER JOIN 语法进行批量处理
同样也是将数据导入至临时表中,但是这里做了一些优化,只导入主键ID,因为删除只需要主键即可
最后会生成类似SQL:
DELETE A
FROM {tableInfo.FullTableName} AS A
INNER JOIN {tableInfo.FullTempTableName} B on A.{firstPrimaryKey} = B.{firstPrimaryKey};
这样就可以快速的进行批量删除.
2.达梦数据库的实现方式
2.1批量插入
其实国产的达梦数据库也提供了对应的SqlBulkCopy类,DmBulkCopy,我们直接按规范实现即可
(注意:达梦数据库的DmBulkCopy,暂时只提供了同步的方法,所以并不支持async异步处理)
2.2批量修改
批量修改的语法达梦就与Mysql差异较大了,但是也提供了对应的SQL
达梦采用 MERGE INTO的语法 可以从临时表中将数据批量更新至源表
2.3批量删除
批量删除也和Mysql大同小异
最后会生成类似如下SQL:
DELETE FROM
{tableInfo.FullTableName} AS A
WHERE A.{firstPrimaryKey} IN
(SELECT B.{firstPrimaryKey} FROM {tableInfo.FullTempTableName} AS B )
从临时表中根据主键删除源表的数据.