📑

Entity Framework Core で Bulk Insert する

2022/03/09に公開
dotnet --version
6.0.200

各データベースプロバイダーに付随する RelationalDbContextOptionsBuilder に MinBatchSize メソッドがあり、Bulk 処理をする最小値を指定することができます。
MinBatchSize メソッドで値を設定し、条件があえば Bulk Insert の SQL を組み立ててくれます。

例として Pomelo.EntityFrameworkCore.MySql で Bulk Insert する場合を見ていきます。
まずは UseMySql の引数で MinBatchSize を指定します。

builder.Services.AddDbContextPool<MySqlDbContext>(options =>
{
    var connectionString = builder.Configuration.GetConnectionString("MySql");
    options.UseMySql(connectionString,
        ServerVersion.AutoDetect(connectionString),
        optionsBuilder => optionsBuilder.MinBatchSize(2));
});

モデルは以下の 2 つのファイルを使用します。

GuidKeyModel.cs
namespace BulkInsertUsingEntityFrameworkCoreSample.Models
{
    public class GuidKeyModel
    {
        public Guid Id { get; set; }
        public int Value { get; set; }
    }
}
IntKeyModel.cs
namespace BulkInsertUsingEntityFrameworkCoreSample.Models
{
    public class IntKeyModel
    {
        public int Id { get; set; }
        public int Value { get; set; }
    }
}

IntKeyModel は Id が AutoIncrement なモデルです。
上記モデルを複数作り保存します。

            _mySqlDbContext.GuidKeyModels.Add(new GuidKeyModel());
            _mySqlDbContext.GuidKeyModels.Add(new GuidKeyModel());
            _mySqlDbContext.IntKeyModels.Add(new IntKeyModel());
            _mySqlDbContext.IntKeyModels.Add(new IntKeyModel());
            _mySqlDbContext.SaveChanges();

実行すると、以下のSQLが発行されます。

Microsoft.EntityFrameworkCore.Database.Command: Information: Executed DbCommand (22ms) [Parameters=[@p0='?' (DbType = Guid), @p1='?' (DbType = Int32), @p2='?' (DbType = Guid), @p3='?' (DbType = Int32), @p4='?' (DbType = Int32), @p5='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
INSERT INTO `GuidKeyModels` (`Id`, `Value`)
VALUES (@p0, @p1),
(@p2, @p3);
INSERT INTO `IntKeyModels` (`Value`)
VALUES (@p4);
SELECT `Id`
FROM `IntKeyModels`
WHERE ROW_COUNT() = 1 AND `Id` = LAST_INSERT_ID();

INSERT INTO `IntKeyModels` (`Value`)
VALUES (@p5);
SELECT `Id`
FROM `IntKeyModels`
WHERE ROW_COUNT() = 1 AND `Id` = LAST_INSERT_ID();

GuidKeyModel が Bulk Insert になっていることが確認できます。
上記のサンプルは以下から clone できます。

https://github.com/mono-matsu/BulkInsertUsingEntityFrameworkCoreSample

Bulk 処理は EFCore.BulkExtensionsEntity Framework Extensions 等、拡張機能として提供されているので用途に合ったものを選ぶのが良さそうです。

Discussion