首页 > 技术文章 > EF Core之批量操作(EFCore.BulkExtensions)

shadowxs 2021-01-17 09:35 原文

EF Core之批量操作(EFCore.BulkExtensions)

EFCore的批量操作性能也在不断完善当中,但还是不够优秀,数据量大的情况下还是要单独处理,这里我们使用EFCore.BulkExtensions(SqlServer)

  • 查询

    EFCore.BulkExtensions的批量查询还是不适合开箱即用,需要做一些基础封装,我们可以在Context里增加扩展方法

    public async Task<List<T>> WhereInAsync<T>(List<T> data, string column) where T : class
    {
        return await MultiWhereInAsync(data, new List<string>() { column });
    }
    
    public async Task<List<T>> MultiWhereInAsync<T>(List<T> data, List<string> column) where T : class
    {
        var bulkReadConfig = new BulkConfig { UpdateByProperties = column };
        return await MyBulkReadAsync(data, bulkReadConfig);
    }
    
    public static List<T> FilterIn<T>(this IList<T> entities) where T : class
    {
        var result = entities?.ToList() ?? new List<T>();
        if (!result.IsNullOrEmpty())
        {
            //这里通过主键过滤掉不存在的数据
            var filterExpression = LambdaUtil.GetExpression<T>("Id", "0", LambdaUtil.ConditionType.GreaterThan);
            if (filterExpression != null)
            {
                result = entities.AsQueryable().Where(filterExpression).ToList();
            }
        }
    
        return result;
    }
    
    public async Task<List<T>> MyBulkReadAsync<T>(
        IList<T> entities,
        BulkConfig bulkConfig = null,
        Action<Decimal> progress = null,
        CancellationToken cancellationToken = default)
        where T : class
    {
        var result = entities?.ToList() ?? new List<T>();
        try
        {
            //由于存在bug,entities必须去重
            await this.BulkReadAsync(entities, bulkConfig, progress, cancellationToken);
            //筛选去掉不存在的
            result = entities.FilterIn();
        }
        catch (SqlException e)
        {
            HandleSqlException(e);
        }
    
        return result;
    }
    
  • 查询使用

    //whereIns数据量过大时,直接使用EFCore的Contains方法会导致sql过长,无法使用,除了使用原生sql,我们还可以封装WhereIn方法
    var result = await _dbContext.WhereInAsync(whereIns, nameof(Model.Field));
    
  • 新增更新

    新增和更新可以做到开箱即用,我们可以在Context里增加扩展方法

    public async Task MyBulkInsertAsync<T>(
        IList<T> entities,
        BulkConfig bulkConfig = null,
        Action<Decimal> progress = null,
        CancellationToken cancellationToken = default)
        where T : class
    {
        try
        {
            await this.BulkInsertAsync(entities, bulkConfig, progress, cancellationToken);
        }
        catch (SqlException e)
        {
            HandleSqlException(e);
        }
    }
    
    public async Task MyBulkUpdateAsync<T>(
        IList<T> entities,
        BulkConfig bulkConfig = null,
        Action<Decimal> progress = null,
        CancellationToken cancellationToken = default)
        where T : class
    {
        try
        {
            await this.BulkUpdateAsync(entities, bulkConfig, progress, cancellationToken);
        }
        catch (SqlException e)
        {
            HandleSqlException(e);
        }
    }
    

推荐阅读