【发布时间】:2020-11-24 14:33:27
【问题描述】:
为什么使用 Select() 比 ToListAsync() 从数据库中检索数据要快得多?我在一个表中有 5000 个虚拟条目。
我的代码:
private IQueryable<TEntity> GetQueryable<TEntity>(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
int? skip = null, int? take = null, bool asNoTracking = false,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> include = null)
where TEntity : class, IEntity
{
IQueryable<TEntity> query = _context.Set<TEntity>();
if (filter != null)
query = query.Where(filter);
if (include != null)
query = include(query);
if (orderBy != null)
query = orderBy(query);
if (skip.HasValue)
query = query.Skip(skip.Value);
if (take.HasValue)
query = query.Take(take.Value);
if (asNoTracking)
query = query.AsNoTracking();
return query;
}
当这样使用方法时:
public virtual async Task<IEnumerable<TEntity>> GetAllAsync<TEntity>(
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
int? skip = null, int? take = null, bool asNoTracking = false,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> include = null)
where TEntity : class, IEntity
{
return await GetQueryable<TEntity>(null, orderBy, skip, take, asNoTracking, include).ToListAsync();
}
这需要 30 秒!
但是当使用这段代码时:
public virtual async Task<IQueryable<dynamic>> GetDynamicAsync<TEntity>(
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
int? skip = null, int? take = null, bool asNoTracking = false,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> include = null,
Expression<Func<TEntity, dynamic>> columns = null)
where TEntity : class, IEntity
{
return GetQueryable<TEntity>(null, orderBy, skip, take, asNoTracking, include).Select(columns);
}
这甚至不需要一秒钟!我想最多 1 秒。
这是为什么呢?有人可以解释吗?即使我在“columns”变量中添加了所有表的列,检索起来仍然非常快。那么这两个查询有什么区别呢?如果这里没有使用 await 也可以吗?我不能使用 await,因为它说 IQueryable 没有 GetAwaiter。这让我很担心。
谢谢!
编辑:添加服务代码
public async Task<ManyResult<LibrariesForTableDTO>> GetLibrariesForTable(DatatableSearchDTO dto)
{
var response = new ManyResult<LibrariesForTableDTO>();
try
{
//var libraries = await _repo.GetDynamicAsync<Library>(columns: x => new { x.Id, x.Name, x.Description });
var libraries = await _repo.GetAllAsync<Library>();
response.Entities = _mapper.Map<List<LibrariesForTableDTO>>(libraries);
response.TotalFilteredEntities = libraries.Count();
response.TotalEntities = libraries.Count();
response.Success = true;
}
catch (Exception e)
{
response.Success = false;
response.Message = "Error retrieviing the libraries.";
_logger.LogError("Error calling GetLibrariesForTable: {0} - {1}", e.Message, e.StackTrace);
}
return response;
}
【问题讨论】:
-
秒只返回普通的 IQueryable ...显然它根本不查询数据库
-
我不明白。我正在检索正确的数据吗?那么我检索数据的方式是否错误?
-
您返回的是不同的东西。您的第一种方法(速度较慢的方法)返回数据。第二个(快速)返回一个可以获取数据的函数。如果您将数据打印到控制台,您会发现它们运行的时间大致相同,因为两者都需要实际获取数据。
-
Select正在返回购物清单 - 操作步骤。ToList(或Select的任何枚举)正在购物。写购物清单很快。去商店买东西很慢。 -
我编辑了我的帖子,我添加了调用查询方法的服务代码。注释的“库”返回数据列表。并且这个映射仍然只需要一秒钟。第二个(未注释)“库”需要 30 秒。你们能告诉我这里的“获取数据”是什么部分吗?因为我真的不明白它什么时候发生。我现在很困惑。谢谢!
标签: c# entity-framework asp.net-core