c# entity freamwork 插入批量数据如何提升性能

在C#中使用Entity Framework(EF)Core进行批量插入数据时,为了提升性能,可以采用以下几种策略:

  1. 批处理操作: EF Core默认情况下并不会一次性执行所有插入操作,而是将它们分批发送给数据库。不过,你可以通过配置DbContext实例的BatchSize属性来显式指定批处理大小。例如,在OnConfiguring方法或DbContext构造函数中设置:

    optionsBuilder.UseSqlServer(
        connectionString,
        x => x.EnableRetryOnFailure()
               .ConfigureCommandTimeout(30)
               .UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery)
               .UseBulkExecution(true) // 从EF Core 6开始支持
               .SetMaxBatchSize(100)); // 自定义批处理大小
    

    注意:UseBulkExecutionSetMaxBatchSize是EF Core 6引入的新特性。

  2. AddRange与SaveChangesAsync: 可以先将多个实体添加到dbContext对象的DbSet ** 中,然后一次性调用SaveChangesAsync方法:

    using (var context = new MyDbContext())
    {
        var entitiesList = new List();
        // 填充entitiesList...
    
        context.MyEntities.AddRange(entitiesList);
        await context.SaveChangesAsync();
    }
    

    这样做的好处是,EF会尽量合并SQL INSERT语句,减少数据库往返次数。

  3. SqlBulkCopy: 对于非常大的批量插入,EF Core本身并不直接提供类似于数据库内置的BULK INSERT功能。但是,你可以手动创建DataTable或使用内存中的IQueryable结果,然后利用System.Data.SqlClient命名空间下的SqlBulkCopy类进行高效的大规模插入:

    using (var context = new MyDbContext())
    {
        var dataTable = new DataTable();
        // 构建dataTable结构并填充数据...
    
        using (var connection = context.Database.GetDbConnection())
        {
            connection.Open();
    
            using (var bulkCopy = new SqlBulkCopy(connection))
            {
                bulkCopy.DestinationTableName = "MyTable";
                bulkCopy.WriteToServer(dataTable);
            }
        }
    }
    

  4. 第三方库: 若需更高级别的批量插入功能,可考虑使用第三方扩展库如Entity Framework Extensions,它提供了对批量插入、更新等操作的优化支持。

  5. 事务管理: 在处理批量插入时确保在一个事务内完成所有操作,避免每次插入都开启新的事务:

    using (var context = new MyDbContext())
    using (var transaction = context.Database.BeginTransaction())
    {
        try
        {
            foreach (var batch in entitiesList.Batch(1000)) // 假设有一个扩展方法 Batch() 将列表切分成子列表
            {
                context.MyEntities.AddRange(batch);
                context.SaveChanges();
            }
    
            transaction.Commit();
        }
        catch
        {
            transaction.Rollback();
            throw;
        }
    }
    

    请根据实际情况选择适合的方法,并注意权衡批量插入时可能带来的内存消耗和数据库连接资源占用问题。同时,请密切关注EF Core版本特性,因为随着框架的发展,可能会有更多原生支持高性能批量插入的功能。

你可能感兴趣的:(数据库)