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);
}
}